OpenDaylight Controller functional modules.
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / FlowProgrammerService.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.protocol_plugin.openflow.internal;
11
12 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
13 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
14 import org.openflow.protocol.OFError;
15 import org.openflow.protocol.OFFlowMod;
16 import org.openflow.protocol.OFMessage;
17 import org.openflow.protocol.OFPort;
18
19 import org.opendaylight.controller.sal.core.Node;
20 import org.opendaylight.controller.sal.core.Node.NodeIDType;
21 import org.opendaylight.controller.sal.flowprogrammer.Flow;
22 import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
23 import org.opendaylight.controller.sal.utils.StatusCode;
24 import org.opendaylight.controller.sal.utils.Status;
25
26 /**
27  * Represents the openflow plugin component in charge of programming the flows
28  * on the switch. It servers the install requests coming from the SAL layer.
29  *
30  *
31  *
32  */
33 public class FlowProgrammerService implements IPluginInFlowProgrammerService {
34     private IController controller;
35
36     public FlowProgrammerService() {
37         controller = null;
38     }
39
40     public void setController(IController core) {
41         this.controller = core;
42     }
43
44     public void unsetController(IController core) {
45         if (this.controller == core) {
46             this.controller = null;
47         }
48     }
49
50     /**
51      * Function called by the dependency manager when all the required
52      * dependencies are satisfied
53      *
54      */
55     void init() {
56     }
57
58     /**
59      * Function called by the dependency manager when at least one
60      * dependency become unsatisfied or when the component is shutting
61      * down because for example bundle is being stopped.
62      *
63      */
64     void destroy() {
65     }
66
67     /**
68      * Function called by dependency manager after "init ()" is called
69      * and after the services provided by the class are registered in
70      * the service registry
71      *
72      */
73     void start() {
74     }
75
76     /**
77      * Function called by the dependency manager before the services
78      * exported by the component are unregistered, this will be
79      * followed by a "destroy ()" calls
80      *
81      */
82     void stop() {
83     }
84
85     @Override
86     public Status addFlow(Node node, Flow flow) {
87         String action = "add";
88         if (!node.getType().equals(NodeIDType.OPENFLOW)) {
89             return new Status(StatusCode.NOTACCEPTABLE,
90                     errorString("send", action, "Invalid node type"));
91         }
92
93         if (controller != null) {
94             ISwitch sw = controller.getSwitch((Long) node.getID());
95             if (sw != null) {
96                 FlowConverter x = new FlowConverter(flow);
97                 OFMessage msg = x.getOFFlowMod(OFFlowMod.OFPFC_ADD, null);
98
99                 /*
100                  * Synchronous message send
101                  */
102                 Object result = sw.syncSend(msg);
103                 if (result instanceof Boolean) {
104                     return ((Boolean) result == Boolean.TRUE) ?
105                             new Status(StatusCode.SUCCESS, null)
106                             : new Status(StatusCode.TIMEOUT,
107                                     errorString(null, action,
108                                             "Request Timed Out"));
109                 } else if (result instanceof OFError) {
110                     return new Status(StatusCode.INTERNALERROR,
111                             errorString("program", action, Utils
112                             .getOFErrorString((OFError) result)));
113                 } else {
114                     return new Status(StatusCode.INTERNALERROR,
115                             errorString("send", action, "Internal Error"));
116                 }
117             } else {
118                 return new Status(StatusCode.GONE, errorString("send", action,
119                                 "Switch is not available"));
120             }
121         }
122         return new Status(StatusCode.INTERNALERROR,
123                 errorString("send", action, "Internal plugin error"));
124     }
125
126     @Override
127     public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
128         String action = "modify";
129         if (!node.getType().equals(NodeIDType.OPENFLOW)) {
130             return new Status(StatusCode.NOTACCEPTABLE,
131                     errorString("send", action, "Invalid node type"));
132         }
133         if (controller != null) {
134             ISwitch sw = controller.getSwitch((Long) node.getID());
135             if (sw != null) {
136                 OFMessage msg1 = null, msg2 = null;
137
138                 // If priority and match portion are the same, send a modification message
139                 if (oldFlow.getPriority() != newFlow.getPriority()
140                         || !oldFlow.getMatch().equals(newFlow.getMatch())) {
141                     msg1 = new FlowConverter(oldFlow).getOFFlowMod(
142                             OFFlowMod.OFPFC_DELETE_STRICT, OFPort.OFPP_NONE);
143                     msg2 = new FlowConverter(newFlow).getOFFlowMod(
144                             OFFlowMod.OFPFC_ADD, null);
145                 } else {
146                     msg1 = new FlowConverter(newFlow).getOFFlowMod(
147                             OFFlowMod.OFPFC_MODIFY_STRICT, null);
148                 }
149                 /*
150                  * Synchronous message send
151                  */
152                 action = (msg2 == null) ? "modify" : "delete";
153                 Object result = sw.syncSend(msg1);
154                 if (result instanceof Boolean) {
155                     if ((Boolean) result == Boolean.FALSE) {
156                         return new Status(StatusCode.TIMEOUT,
157                                 errorString(null, action,
158                                         "Request Timed Out"));
159                     } else if (msg2 == null) {
160                         return new Status(StatusCode.SUCCESS, null);
161                     }
162                 } else if (result instanceof OFError) {
163                     return new Status(StatusCode.INTERNALERROR,
164                             errorString("program", action, Utils
165                             .getOFErrorString((OFError) result)));
166                 } else {
167                     return new Status(StatusCode.INTERNALERROR,
168                             errorString("send", action, "Internal Error"));
169                 }
170
171                 if (msg2 != null) {
172                     action = "add";
173                     result = sw.syncSend(msg2);
174                     if (result instanceof Boolean) {
175                         return ((Boolean) result == Boolean.TRUE) ?
176                                 new Status(StatusCode.SUCCESS, null)
177                                 : new Status(StatusCode.TIMEOUT,
178                                         errorString(null, action,
179                                                 "Request Timed Out"));
180                     } else if (result instanceof OFError) {
181                         return new Status(StatusCode.INTERNALERROR,
182                                 errorString("program", action, Utils
183                                 .getOFErrorString((OFError) result)));
184                     } else {
185                         return new Status(StatusCode.INTERNALERROR,
186                                 errorString("send", action, "Internal Error"));
187                     }
188                 }
189             } else {
190                 return new Status(StatusCode.GONE, errorString("send", action,
191                         "Switch is not available"));
192             }
193         }
194         return new Status(StatusCode.INTERNALERROR,
195                 errorString("send", action, "Internal plugin error"));
196     }
197
198     @Override
199     public Status removeFlow(Node node, Flow flow) {
200         String action = "remove";
201         if (!node.getType().equals(NodeIDType.OPENFLOW)) {
202             return new Status(StatusCode.NOTACCEPTABLE,
203                     errorString("send", action, "Invalid node type"));
204         }
205         if (controller != null) {
206             ISwitch sw = controller.getSwitch((Long) node.getID());
207             if (sw != null) {
208                 OFMessage msg = new FlowConverter(flow).getOFFlowMod(
209                         OFFlowMod.OFPFC_DELETE_STRICT, OFPort.OFPP_NONE);
210                 Object result = sw.syncSend(msg);
211                 if (result instanceof Boolean) {
212                     return ((Boolean) result == Boolean.TRUE) ?
213                             new Status(StatusCode.SUCCESS, null)
214                             : new Status(StatusCode.TIMEOUT,
215                                     errorString(null, action,
216                                             "Request Timed Out"));
217                 } else if (result instanceof OFError) {
218                     return new Status(StatusCode.INTERNALERROR,
219                             errorString("program", action, Utils
220                             .getOFErrorString((OFError) result)));
221                 } else {
222                     return new Status(StatusCode.INTERNALERROR,
223                             errorString("send", action, "Internal Error"));
224                 }
225             } else {
226                 return new Status(StatusCode.GONE,  errorString("send", action,
227                         "Switch is not available"));
228             }
229         }
230         return new Status(StatusCode.INTERNALERROR,
231                 errorString("send", action, "Internal plugin error"));
232     }
233
234     @Override
235     public Status removeAllFlows(Node node) {
236         return new Status(StatusCode.SUCCESS, null);
237     }
238
239     private String errorString(String phase, String action, String cause) {
240         return "Failed to "
241                 + ((phase != null) ? phase + " the " + action
242                         + " flow message: " : action + " the flow: ") + cause;
243     }
244
245 }