3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
10 package org.opendaylight.controller.protocol_plugin.openflow.internal;
12 import java.nio.ByteBuffer;
13 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
14 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
15 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error;
16 import org.openflow.protocol.OFError;
17 import org.openflow.protocol.OFFlowMod;
18 import org.openflow.protocol.OFMessage;
19 import org.openflow.protocol.OFPort;
21 import org.opendaylight.controller.sal.core.Node;
22 import org.opendaylight.controller.sal.core.Node.NodeIDType;
23 import org.opendaylight.controller.sal.flowprogrammer.Flow;
24 import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
25 import org.opendaylight.controller.sal.utils.StatusCode;
26 import org.opendaylight.controller.sal.utils.Status;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * Represents the openflow plugin component in charge of programming the flows
32 * on the switch. It servers the install requests coming from the SAL layer.
37 public class FlowProgrammerService implements IPluginInFlowProgrammerService {
38 private static final Logger log = LoggerFactory
39 .getLogger(FlowProgrammerService.class);
40 private IController controller;
42 public FlowProgrammerService() {
46 public void setController(IController core) {
47 this.controller = core;
50 public void unsetController(IController core) {
51 if (this.controller == core) {
52 this.controller = null;
57 * Function called by the dependency manager when all the required
58 * dependencies are satisfied
65 * Function called by the dependency manager when at least one
66 * dependency become unsatisfied or when the component is shutting
67 * down because for example bundle is being stopped.
74 * Function called by dependency manager after "init ()" is called
75 * and after the services provided by the class are registered in
76 * the service registry
83 * Function called by the dependency manager before the services
84 * exported by the component are unregistered, this will be
85 * followed by a "destroy ()" calls
92 public Status addFlow(Node node, Flow flow) {
93 String action = "add";
94 if (!node.getType().equals(NodeIDType.OPENFLOW)) {
95 return new Status(StatusCode.NOTACCEPTABLE,
96 errorString("send", action, "Invalid node type"));
99 if (controller != null) {
100 ISwitch sw = controller.getSwitch((Long) node.getID());
102 FlowConverter x = new FlowConverter(flow);
103 OFMessage msg = x.getOFFlowMod(OFFlowMod.OFPFC_ADD, null);
106 * Synchronous message send
108 Object result = sw.syncSend(msg);
109 if (result instanceof Boolean) {
110 return ((Boolean) result == Boolean.TRUE) ?
111 new Status(StatusCode.SUCCESS, null)
112 : new Status(StatusCode.TIMEOUT,
113 errorString(null, action,
114 "Request Timed Out"));
115 } else if (result instanceof OFError) {
116 OFError res = (OFError) result;
117 if (res.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) {
118 V6Error er = new V6Error(res);
119 byte[] b = res.getError();
120 ByteBuffer bb = ByteBuffer.allocate(b.length);
124 log.trace("V6Error {}",er);
125 return new Status(StatusCode.INTERNALERROR,
126 errorString("program", action, "Vendor Extension Internal Error"));
128 return new Status(StatusCode.INTERNALERROR,
129 errorString("program", action, Utils
130 .getOFErrorString(res)));
132 return new Status(StatusCode.INTERNALERROR,
133 errorString("send", action, "Internal Error"));
136 return new Status(StatusCode.GONE, errorString("send", action,
137 "Switch is not available"));
140 return new Status(StatusCode.INTERNALERROR,
141 errorString("send", action, "Internal plugin error"));
145 public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
146 String action = "modify";
147 if (!node.getType().equals(NodeIDType.OPENFLOW)) {
148 return new Status(StatusCode.NOTACCEPTABLE,
149 errorString("send", action, "Invalid node type"));
151 if (controller != null) {
152 ISwitch sw = controller.getSwitch((Long) node.getID());
154 OFMessage msg1 = null, msg2 = null;
156 // If priority and match portion are the same, send a modification message
157 if (oldFlow.getPriority() != newFlow.getPriority()
158 || !oldFlow.getMatch().equals(newFlow.getMatch())) {
159 msg1 = new FlowConverter(oldFlow).getOFFlowMod(
160 OFFlowMod.OFPFC_DELETE_STRICT, OFPort.OFPP_NONE);
161 msg2 = new FlowConverter(newFlow).getOFFlowMod(
162 OFFlowMod.OFPFC_ADD, null);
164 msg1 = new FlowConverter(newFlow).getOFFlowMod(
165 OFFlowMod.OFPFC_MODIFY_STRICT, null);
168 * Synchronous message send
170 action = (msg2 == null) ? "modify" : "delete";
171 Object result = sw.syncSend(msg1);
172 if (result instanceof Boolean) {
173 if ((Boolean) result == Boolean.FALSE) {
174 return new Status(StatusCode.TIMEOUT,
175 errorString(null, action,
176 "Request Timed Out"));
177 } else if (msg2 == null) {
178 return new Status(StatusCode.SUCCESS, null);
180 } else if (result instanceof OFError) {
181 return new Status(StatusCode.INTERNALERROR,
182 errorString("program", action, Utils
183 .getOFErrorString((OFError) result)));
185 return new Status(StatusCode.INTERNALERROR,
186 errorString("send", action, "Internal Error"));
191 result = sw.syncSend(msg2);
192 if (result instanceof Boolean) {
193 return ((Boolean) result == Boolean.TRUE) ?
194 new Status(StatusCode.SUCCESS, null)
195 : new Status(StatusCode.TIMEOUT,
196 errorString(null, action,
197 "Request Timed Out"));
198 } else if (result instanceof OFError) {
199 return new Status(StatusCode.INTERNALERROR,
200 errorString("program", action, Utils
201 .getOFErrorString((OFError) result)));
203 return new Status(StatusCode.INTERNALERROR,
204 errorString("send", action, "Internal Error"));
208 return new Status(StatusCode.GONE, errorString("send", action,
209 "Switch is not available"));
212 return new Status(StatusCode.INTERNALERROR,
213 errorString("send", action, "Internal plugin error"));
217 public Status removeFlow(Node node, Flow flow) {
218 String action = "remove";
219 if (!node.getType().equals(NodeIDType.OPENFLOW)) {
220 return new Status(StatusCode.NOTACCEPTABLE,
221 errorString("send", action, "Invalid node type"));
223 if (controller != null) {
224 ISwitch sw = controller.getSwitch((Long) node.getID());
226 OFMessage msg = new FlowConverter(flow).getOFFlowMod(
227 OFFlowMod.OFPFC_DELETE_STRICT, OFPort.OFPP_NONE);
228 Object result = sw.syncSend(msg);
229 if (result instanceof Boolean) {
230 return ((Boolean) result == Boolean.TRUE) ?
231 new Status(StatusCode.SUCCESS, null)
232 : new Status(StatusCode.TIMEOUT,
233 errorString(null, action,
234 "Request Timed Out"));
235 } else if (result instanceof OFError) {
236 return new Status(StatusCode.INTERNALERROR,
237 errorString("program", action, Utils
238 .getOFErrorString((OFError) result)));
240 return new Status(StatusCode.INTERNALERROR,
241 errorString("send", action, "Internal Error"));
244 return new Status(StatusCode.GONE, errorString("send", action,
245 "Switch is not available"));
248 return new Status(StatusCode.INTERNALERROR,
249 errorString("send", action, "Internal plugin error"));
253 public Status removeAllFlows(Node node) {
254 return new Status(StatusCode.SUCCESS, null);
257 private String errorString(String phase, String action, String cause) {
259 + ((phase != null) ? phase + " the " + action
260 + " flow message: " : action + " the flow: ") + cause;