1 package org.opendaylight.ovsdb.neutron;
3 import java.util.ArrayList;
4 import java.util.Collections;
9 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
10 import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
11 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
12 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
13 import org.opendaylight.controller.sal.action.ActionType;
14 import org.opendaylight.controller.sal.core.Node;
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.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * OpenStack Neutron with the OpenVswitch data plan relies on a typical OVS bridge configurations that
33 * consists of br-int (Integration Bridge), br-tun (Tunnel bridge), br-ex (External bridge).
35 * In DevStack like setups, the br-tun is not automatically created on the controller nodes.
36 * Hence this class attempts to bring all the nodes to be elibible for OpenStack operations.
39 public class InternalNetworkManager {
40 static final Logger logger = LoggerFactory.getLogger(InternalNetworkManager.class);
42 private static InternalNetworkManager internalNetwork = new InternalNetworkManager();
43 private InternalNetworkManager() {
46 public static InternalNetworkManager getManager() {
47 return internalNetwork;
50 public String getInternalBridgeUUID (Node node, String bridgeName) {
52 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
53 Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
54 if (bridgeTable == null) return null;
55 for (String key : bridgeTable.keySet()) {
56 Bridge bridge = (Bridge)bridgeTable.get(key);
57 if (bridge.getName().equals(bridgeName)) return key;
59 } catch (Exception e) {
60 logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
65 public boolean isInternalNetworkNeutronReady(Node node) throws Exception {
66 if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getIntegrationBridgeName()) != null) {
73 public boolean isInternalNetworkOverlayReady(Node node) throws Exception {
74 if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()) != null) {
81 public Status createInternalNetworkForOverlay(Node node) throws Exception {
82 if (!isInternalNetworkNeutronReady(node)) {
83 logger.error("Integration Bridge is not available in Node {}", node);
84 return new Status(StatusCode.NOTACCEPTABLE, "Integration Bridge is not avaialble in Node " + node);
86 if (isInternalNetworkOverlayReady(node)) {
87 logger.error("Network Overlay Bridge is already present in Node {}", node);
88 return new Status(StatusCode.NOTACCEPTABLE, "Network Overlay Bridge is already present in Node " + node);
98 options: {peer=patch-tun}
104 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
105 Bridge brTun = new Bridge();
106 brTun.setName(AdminConfigManager.getManager().getTunnelBridgeName());
107 // Create br-tun bridge
108 Status status = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, brTun);
109 if (!status.isSuccess()) return status;
110 String bridgeUUID = status.getDescription();
112 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
113 connectionService.setOFController(node, bridgeUUID);
115 Port port = new Port();
116 port.setName(brTun.getName());
117 status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
119 String patchInt = AdminConfigManager.getManager().getPatchToIntegration();
120 String patchTun = AdminConfigManager.getManager().getPatchToTunnel();
122 status = addPatchPort(node, bridgeUUID, patchInt, patchTun);
123 if (!status.isSuccess()) return status;
125 // Create the corresponding patch-tun port in br-int
126 Map<String, Table<?>> bridges = ovsdbTable.getRows(node, Bridge.NAME.getName());
127 for (String brIntUUID : bridges.keySet()) {
128 Bridge brInt = (Bridge) bridges.get(brIntUUID);
129 if (brInt.getName().equalsIgnoreCase(AdminConfigManager.getManager().getIntegrationBridgeName())) {
130 return addPatchPort(node, brIntUUID, patchTun, patchInt);
137 private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
138 Status status = null;
139 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
141 Port patchPort = new Port();
142 patchPort.setName(portName);
143 // Create patch-int port and interface
144 status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, patchPort);
145 if (!status.isSuccess()) return status;
147 String patchPortUUID = status.getDescription();
149 String interfaceUUID = null;
151 while ((interfaceUUID == null) && (timeout > 0)) {
152 patchPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), patchPortUUID);
153 OvsDBSet<UUID> interfaces = patchPort.getInterfaces();
154 if (interfaces == null || interfaces.size() == 0) {
155 // Wait for the OVSDB update to sync up the Local cache.
160 interfaceUUID = interfaces.toArray()[0].toString();
163 if (interfaceUUID == null) {
164 return new Status(StatusCode.INTERNALERROR);
167 Interface tunInterface = new Interface();
168 tunInterface.setType("patch");
169 OvsDBMap<String, String> options = new OvsDBMap<String, String>();
170 options.put("peer", patchName);
171 tunInterface.setOptions(options);
172 status = ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, tunInterface);
177 private void prepareInternalNetwork (NeutronNetwork network, Node node) {
178 // vlan, vxlan, and gre
179 if (network.getProviderNetworkType().equalsIgnoreCase("gre") ||
180 network.getProviderNetworkType().equalsIgnoreCase("vxlan") ||
181 network.getProviderNetworkType().equalsIgnoreCase("vlan")) {
184 if (!this.isInternalNetworkOverlayReady(node)) {
185 this.createInternalNetworkForOverlay(node);
187 } catch (Exception e) {
192 if (!this.isInternalNetworkNeutronReady(node)) {
194 // this.createInternalNetworkForNeutron(node);
196 } catch (Exception e) {
201 this.initializeFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName());
204 private void initializeFlowRules(Node node, String bridgeName) {
205 String brIntId = this.getInternalBridgeUUID(node, bridgeName);
206 if (brIntId == null) {
207 logger.error("Failed to initialize Flow Rules for {}", node);
211 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
212 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
213 Set<String> dpids = bridge.getDatapath_id();
214 if (dpids == null || dpids.size() == 0) return;
215 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
216 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
217 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
218 IForwardingRulesManager.class, "default", this);
219 FlowConfig flow = new FlowConfig();
220 flow.setName("IntegrationBridgeNormal");
221 flow.setNode(ofNode);
222 flow.setPriority("1");
223 List<String> normalAction = new ArrayList<String>();
224 normalAction.add(ActionType.HW_PATH.toString());
225 flow.setActions(normalAction);
226 Status status = frm.addStaticFlow(flow);
227 logger.debug("Flow Programming Status {} for Flow {} on {} / {}", status, flow, ofNode, node);
228 } catch (Exception e) {
229 logger.error("Failed to initialize Flow Rules for {}", node, e);
233 public void prepareInternalNetwork(NeutronNetwork network) {
234 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
235 List<Node> nodes = connectionService.getNodes();
236 for (Node node : nodes) {
237 prepareInternalNetwork(network, node);
241 public void prepareInternalNetwork(Node node) {
242 INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
243 List <NeutronNetwork> networks = neutronNetworkService.getAllNetworks();
244 for (NeutronNetwork network : networks) {
245 prepareInternalNetwork(network, node);
249 public static List safe( List other ) {
250 return other == null ? Collections.EMPTY_LIST : other;