1 package org.opendaylight.ovsdb.neutron;
3 import java.util.ArrayList;
8 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
9 import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
10 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
11 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
12 import org.opendaylight.controller.sal.action.ActionType;
13 import org.opendaylight.controller.sal.core.Node;
14 import org.opendaylight.controller.sal.utils.EtherTypes;
15 import org.opendaylight.controller.sal.utils.HexEncode;
16 import org.opendaylight.controller.sal.utils.ServiceHelper;
17 import org.opendaylight.controller.sal.utils.Status;
18 import org.opendaylight.controller.sal.utils.StatusCode;
19 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
20 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.ovsdb.lib.table.Bridge;
23 import org.opendaylight.ovsdb.lib.table.Interface;
24 import org.opendaylight.ovsdb.lib.table.Port;
25 import org.opendaylight.ovsdb.lib.table.internal.Table;
26 import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
27 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
28 import org.opendaylight.ovsdb.plugin.StatusWithUuid;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * OpenStack Neutron with the OpenVswitch data plan relies on a typical OVS bridge configurations that
34 * consists of br-int (Integration Bridge), br-tun (Tunnel bridge), br-ex (External bridge).
36 * In DevStack like setups, the br-tun is not automatically created on the controller nodes.
37 * Hence this class attempts to bring all the nodes to be elibible for OpenStack operations.
40 public class InternalNetworkManager {
41 static final Logger logger = LoggerFactory.getLogger(InternalNetworkManager.class);
42 private static final int LLDP_PRIORITY = 1000;
43 private static final int NORMAL_PRIORITY = 500;
45 private static InternalNetworkManager internalNetwork = new InternalNetworkManager();
46 private InternalNetworkManager() {
49 public static InternalNetworkManager getManager() {
50 return internalNetwork;
53 public String getInternalBridgeUUID (Node node, String bridgeName) {
55 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
56 Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
57 if (bridgeTable == null) return null;
58 for (String key : bridgeTable.keySet()) {
59 Bridge bridge = (Bridge)bridgeTable.get(key);
60 if (bridge.getName().equals(bridgeName)) return key;
62 } catch (Exception e) {
63 logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
68 public boolean isInternalNetworkNeutronReady(Node node) {
69 if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getIntegrationBridgeName()) != null) {
76 public boolean isInternalNetworkOverlayReady(Node node) {
77 if (!this.isInternalNetworkNeutronReady(node)) {
80 if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()) != null) {
88 * Lets create these if not already present :
94 options: {peer=patch-int}
102 options: {peer=patch-tun}
107 public void createInternalNetworkForOverlay(Node node) throws Exception {
108 String brTun = AdminConfigManager.getManager().getTunnelBridgeName();
109 String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
110 String patchInt = AdminConfigManager.getManager().getPatchToIntegration();
111 String patchTun = AdminConfigManager.getManager().getPatchToTunnel();
113 Status status = this.addInternalBridge(node, brInt, patchTun, patchInt);
114 if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
115 status = this.addInternalBridge(node, brTun, patchInt, patchTun);
116 if (!status.isSuccess()) logger.debug("Tunnel Bridge Creation Status : "+status.toString());
120 * Lets create these if not already present :
127 public void createInternalNetworkForNeutron(Node node) throws Exception {
128 String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
130 Status status = this.addInternalBridge(node, brInt, null, null);
131 if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
134 private Status addInternalBridge (Node node, String bridgeName, String localPathName, String remotePatchName) throws Exception {
135 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
137 String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
138 if (bridgeUUID == null) {
139 Bridge bridge = new Bridge();
140 bridge.setName(bridgeName);
142 StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, bridge);
143 if (!statusWithUuid.isSuccess()) return statusWithUuid;
144 bridgeUUID = statusWithUuid.getUuid().toString();
145 Port port = new Port();
146 port.setName(bridgeName);
147 ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
150 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
151 connectionService.setOFController(node, bridgeUUID);
153 if (localPathName != null && remotePatchName != null) {
154 return addPatchPort(node, bridgeUUID, localPathName, remotePatchName);
156 return new Status(StatusCode.SUCCESS);
159 private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
160 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
162 Port patchPort = new Port();
163 patchPort.setName(portName);
164 // Create patch port and interface
165 StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, patchPort);
166 if (!statusWithUuid.isSuccess()) return statusWithUuid;
168 String patchPortUUID = statusWithUuid.getUuid().toString();
170 String interfaceUUID = null;
172 while ((interfaceUUID == null) && (timeout > 0)) {
173 patchPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), patchPortUUID);
174 OvsDBSet<UUID> interfaces = patchPort.getInterfaces();
175 if (interfaces == null || interfaces.size() == 0) {
176 // Wait for the OVSDB update to sync up the Local cache.
181 interfaceUUID = interfaces.toArray()[0].toString();
184 if (interfaceUUID == null) {
185 return new Status(StatusCode.INTERNALERROR);
188 Interface tunInterface = new Interface();
189 tunInterface.setType("patch");
190 OvsDBMap<String, String> options = new OvsDBMap<String, String>();
191 options.put("peer", patchName);
192 tunInterface.setOptions(options);
193 return ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, tunInterface);
196 private void prepareInternalNetwork (NeutronNetwork network, Node node) {
197 // vlan, vxlan, and gre
198 if (network.getProviderNetworkType().equalsIgnoreCase("gre") ||
199 network.getProviderNetworkType().equalsIgnoreCase("vxlan") ||
200 network.getProviderNetworkType().equalsIgnoreCase("vlan")) {
203 this.createInternalNetworkForOverlay(node);
204 } catch (Exception e) {
205 logger.error("Failed to create internal network for overlay on node " + node, e);
209 this.createInternalNetworkForNeutron(node);
210 } catch (Exception e) {
211 logger.error("Failed to create internal network for overlay on node " + node, e);
215 this.initializeOFNormalFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName());
216 this.initializeLLDPFlowRules(node, AdminConfigManager.getManager().getTunnelBridgeName());
217 this.initializeLLDPFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName());
220 private void initializeOFNormalFlowRules(Node node, String bridgeName) {
221 String brIntId = this.getInternalBridgeUUID(node, bridgeName);
222 if (brIntId == null) {
223 logger.error("Failed to initialize Flow Rules for {}", node);
227 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
228 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
229 Set<String> dpids = bridge.getDatapath_id();
230 if (dpids == null || dpids.size() == 0) return;
231 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
232 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
233 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
234 IForwardingRulesManager.class, "default", this);
235 String flowName = ActionType.HW_PATH.toString();
236 if (frm.getStaticFlow(flowName, ofNode) != null) {
237 logger.debug("Static Flow {} already programmed in the node {}", flowName, ofNode);
240 FlowConfig flow = new FlowConfig();
241 flow.setName("IntegrationBridgeNormal");
242 flow.setNode(ofNode);
243 flow.setPriority(NORMAL_PRIORITY+"");
244 List<String> normalAction = new ArrayList<String>();
245 normalAction.add(flowName);
246 flow.setActions(normalAction);
247 Status status = frm.addStaticFlow(flow);
248 logger.debug("Flow Programming Status {} for Flow {} on {} / {}", status, flow, ofNode, node);
249 } catch (Exception e) {
250 logger.error("Failed to initialize Flow Rules for {}", node, e);
254 private void initializeLLDPFlowRules(Node node, String bridgeName) {
255 String brIntId = this.getInternalBridgeUUID(node, bridgeName);
256 if (brIntId == null) {
257 logger.error("Failed to initialize Flow Rules for {}", node);
261 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
262 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
263 Set<String> dpids = bridge.getDatapath_id();
264 if (dpids == null || dpids.size() == 0) return;
265 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
266 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
267 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
268 IForwardingRulesManager.class, "default", this);
269 String flowName = "PuntLLDP";
270 if (frm.getStaticFlow(flowName, ofNode) != null) {
271 logger.debug("Static Flow {} already programmed in the node {}", flowName, ofNode);
275 List<String> puntAction = new ArrayList<String>();
276 puntAction.add(ActionType.CONTROLLER.toString());
278 FlowConfig allowLLDP = new FlowConfig();
279 allowLLDP.setInstallInHw(true);
280 allowLLDP.setName(flowName);
281 allowLLDP.setPriority(LLDP_PRIORITY+"");
282 allowLLDP.setNode(ofNode);
283 allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue())
285 allowLLDP.setActions(puntAction);
286 Status status = frm.addStaticFlow(allowLLDP);
287 logger.debug("Flow Programming Status {} for Flow {} on {} / {}", status, allowLLDP, ofNode, node);
288 } catch (Exception e) {
289 logger.error("Failed to initialize Flow Rules for {}", node, e);
293 public void prepareInternalNetwork(NeutronNetwork network) {
294 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
295 List<Node> nodes = connectionService.getNodes();
296 for (Node node : nodes) {
297 prepareInternalNetwork(network, node);
301 public void prepareInternalNetwork(Node node) {
302 INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
303 List <NeutronNetwork> networks = neutronNetworkService.getAllNetworks();
304 for (NeutronNetwork network : networks) {
305 prepareInternalNetwork(network, node);