2 * Copyright (C) 2013 Red Hat, Inc.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague, Dave Tucker
10 package org.opendaylight.ovsdb.neutron.provider;
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
19 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
20 import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
21 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
22 import org.opendaylight.controller.sal.action.ActionType;
23 import org.opendaylight.controller.sal.core.Node;
24 import org.opendaylight.controller.sal.utils.EtherTypes;
25 import org.opendaylight.controller.sal.utils.HexEncode;
26 import org.opendaylight.controller.sal.utils.ServiceHelper;
27 import org.opendaylight.controller.sal.utils.Status;
28 import org.opendaylight.controller.sal.utils.StatusCode;
29 import org.opendaylight.controller.switchmanager.ISwitchManager;
30 import org.opendaylight.controller.switchmanager.Switch;
31 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
32 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
33 import org.opendaylight.ovsdb.lib.notation.UUID;
34 import org.opendaylight.ovsdb.lib.table.Bridge;
35 import org.opendaylight.ovsdb.lib.table.Interface;
36 import org.opendaylight.ovsdb.lib.table.Port;
37 import org.opendaylight.ovsdb.lib.table.internal.Table;
38 import org.opendaylight.ovsdb.neutron.NetworkHandler;
39 import org.opendaylight.ovsdb.neutron.IAdminConfigManager;
40 import org.opendaylight.ovsdb.neutron.IInternalNetworkManager;
41 import org.opendaylight.ovsdb.neutron.ITenantNetworkManager;
42 import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
43 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
44 import org.opendaylight.ovsdb.plugin.StatusWithUuid;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 public class OF10Provider implements NetworkProvider {
50 private static final Logger logger = LoggerFactory.getLogger(OF10Provider.class);
51 private static final int INGRESS_TUNNEL_FLOW_PRIORITY = 100;
52 private static final int EGRESS_TUNNEL_FLOW_PRIORITY = 100;
53 private static final int DROP_FLOW_PRIORITY = 10;
54 private static final int FLOOD_TUNNEL_FLOW_PRIORITY = 50;
56 private IAdminConfigManager adminConfigManager;
57 private IInternalNetworkManager internalNetworkManager;
58 private ITenantNetworkManager tenantNetworkManager;
60 public OF10Provider(IAdminConfigManager adminConfigManager,
61 IInternalNetworkManager internalNetworkManager,
62 ITenantNetworkManager tenantNetworkManager) {
63 this.adminConfigManager = adminConfigManager;
64 this.internalNetworkManager = internalNetworkManager;
65 this.tenantNetworkManager = tenantNetworkManager;
69 public boolean hasPerTenantTunneling() {
73 private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
74 InetAddress srcTunnelEndPoint = adminConfigManager.getTunnelEndPoint(node);
75 if (srcTunnelEndPoint == null) {
76 logger.error("Tunnel Endpoint not configured for Node {}", node);
77 return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
80 if (!internalNetworkManager.isInternalNetworkOverlayReady(node)) {
81 logger.warn("{} is not Overlay ready. It might be an OpenStack Controller Node", node);
82 return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
85 if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
86 logger.debug(node+" has no network corresponding to segment "+ tunnelKey);
87 return new Status(StatusCode.NOTACCEPTABLE, node+" has no network corresponding to segment "+ tunnelKey);
89 return new Status(StatusCode.SUCCESS);
92 private Status getVlanReadinessStatus (Node node, String segmentationId) {
93 if (!internalNetworkManager.isInternalNetworkOverlayReady(node)) {
94 logger.warn("{} is not Overlay ready. It might be an OpenStack Controller Node", node);
95 return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
98 if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, segmentationId)) {
99 logger.debug(node+" has no network corresponding to segment "+ segmentationId);
100 return new Status(StatusCode.NOTACCEPTABLE, node+" has no network corresponding to segment "+ segmentationId);
102 return new Status(StatusCode.SUCCESS);
106 * Program OF1.0 Flow rules on br-tun on the ingress direction from the network towards the br-int.
107 * The logic is to simply match on the incoming tunnel OF-Port (which carries the TenantNetwork GRE-Key)
108 * and rewrite the Corresponding internal Vlan and pass it on to br-int via the patch port.
110 private void programLocalIngressTunnelBridgeRules(Node node, int tunnelOFPort, int internalVlan, int patchPort) {
111 String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
112 if (brNetId == null) {
113 logger.error("Failed to initialize Flow Rules for {}", node);
117 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
118 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
119 Set<String> dpids = bridge.getDatapath_id();
120 if (dpids == null || dpids.size() == 0) return;
121 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
122 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
123 String flowName = "TepMatch"+tunnelOFPort+""+internalVlan;
124 FlowConfig flow = new FlowConfig();
125 flow.setName(flowName);
126 flow.setNode(ofNode);
127 flow.setInstallInHw(true);
128 flow.setPriority(INGRESS_TUNNEL_FLOW_PRIORITY+"");
129 flow.setIngressPort(tunnelOFPort+"");
130 List<String> actions = new ArrayList<String>();
131 actions.add(ActionType.SET_VLAN_ID+"="+internalVlan);
132 actions.add(ActionType.OUTPUT.toString()+"="+patchPort);
133 flow.setActions(actions);
134 Status status = this.addStaticFlow(ofNode, flow);
135 logger.debug("Local Ingress Flow Programming Status {} for Flow {} on {} / {}", status, flow, ofNode, node);
136 } catch (Exception e) {
137 logger.error("Failed to initialize Flow Rules for {}", node, e);
141 private void removeLocalIngressTunnelBridgeRules(Node node, int tunnelOFPort, int internalVlan, int patchPort) {
142 String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
143 if (brNetId == null) {
144 logger.error("Failed to remove Flow Rules for {}", node);
148 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
149 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
150 Set<String> dpids = bridge.getDatapath_id();
151 if (dpids == null || dpids.size() == 0) return;
152 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
153 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
154 String flowName = "TepMatch"+tunnelOFPort+""+internalVlan;
156 Status status = this.deleteStaticFlow(ofNode, flowName);
157 logger.debug("Local Ingress Flow Removal Status {} for Flow {} on {} / {}", status, flowName, ofNode, node);
158 } catch (Exception e) {
159 logger.error("Failed to Remove Flow Rules for {}", node, e);
164 * Program OF1.0 Flow rules on br-tun on the remote Node on its egress direction towards the overlay network
165 * for a VM (with the attachedMac).
166 * The logic is to simply match on the incoming vlan, mac from the patch-port connected to br-int (patch-int)
167 * and output the traffic to the appropriate GRE Tunnel (which carries the GRE-Key for that Tenant Network).
168 * Also perform the Strip-Vlan action.
170 private void programRemoteEgressTunnelBridgeRules(Node node, int patchPort, String attachedMac,
171 int internalVlan, int tunnelOFPort) {
172 String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
173 if (brNetId == null) {
174 logger.error("Failed to initialize Flow Rules for {}", node);
178 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
179 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
180 Set<String> dpids = bridge.getDatapath_id();
181 if (dpids == null || dpids.size() == 0) return;
182 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
183 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
184 String flowName = "TepMatch"+tunnelOFPort+""+internalVlan+""+HexEncode.stringToLong(attachedMac);
185 FlowConfig flow = new FlowConfig();
186 flow.setName(flowName);
187 flow.setNode(ofNode);
188 flow.setInstallInHw(true);
189 flow.setPriority(EGRESS_TUNNEL_FLOW_PRIORITY+"");
190 flow.setDstMac(attachedMac);
191 flow.setIngressPort(patchPort+"");
192 flow.setVlanId(internalVlan+"");
193 List<String> actions = new ArrayList<String>();
194 actions.add(ActionType.POP_VLAN.toString());
195 actions.add(ActionType.OUTPUT.toString()+"="+tunnelOFPort);
196 flow.setActions(actions);
197 Status status = this.addStaticFlow(ofNode, flow);
198 logger.debug("Remote Egress Flow Programming Status {} for Flow {} on {} / {}", status, flow, ofNode, node);
199 } catch (Exception e) {
200 logger.error("Failed to initialize Flow Rules for {}", node, e);
204 private void removeRemoteEgressTunnelBridgeRules(Node node, int patchPort, String attachedMac,
205 int internalVlan, int tunnelOFPort) {
206 String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
207 if (brNetId == null) {
208 logger.error("Failed to initialize Flow Rules for {}", node);
212 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
213 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
214 Set<String> dpids = bridge.getDatapath_id();
215 if (dpids == null || dpids.size() == 0) return;
216 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
217 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
218 String flowName = "TepMatch"+tunnelOFPort+""+internalVlan+""+HexEncode.stringToLong(attachedMac);
219 Status status = this.deleteStaticFlow(ofNode, flowName);
220 logger.debug("Remote Egress Flow Removal Status {} for Flow {} on {} / {}", status, flowName, ofNode, node);
221 } catch (Exception e) {
222 logger.error("Failed to Remove Flow Rules for {}", node, e);
227 * Program OF1.0 Flow rules to flood the broadcast & unknown-unicast traffic over br-tun on the egress direction
228 * towards the network on all the overlay tunnels that corresponds to the tenant network.
229 * The logic is to simply match on the incoming vlan, mac from the patch-port connected to br-int (patch-int)
230 * and output the traffic to all the GRE-Tunnels for this Tenant Network (which carries the GRE-Key).
231 * Also perform the Strip-Vlan action.
233 private void programFloodEgressTunnelBridgeRules(Node node, int patchPort, int internalVlan, int tunnelOFPort) {
234 String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
235 if (brNetId == null) {
236 logger.error("Failed to initialize Flow Rules for {}", node);
240 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
241 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
242 Set<String> dpids = bridge.getDatapath_id();
243 if (dpids == null || dpids.size() == 0) return;
244 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
245 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
246 String flowName = "TepFlood"+internalVlan;
247 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
248 IForwardingRulesManager.class, "default", this);
249 FlowConfig existingFlowConfig = frm.getStaticFlow(flowName, ofNode);
250 FlowConfig flow = existingFlowConfig;
251 Status status = null;
253 flow = new FlowConfig();
254 flow.setName(flowName);
255 flow.setNode(ofNode);
256 flow.setPriority(FLOOD_TUNNEL_FLOW_PRIORITY+"");
257 flow.setIngressPort(patchPort+"");
258 flow.setVlanId(internalVlan+"");
259 List<String> actions = new ArrayList<String>();
260 actions.add(ActionType.POP_VLAN.toString());
261 actions.add(ActionType.OUTPUT.toString()+"="+tunnelOFPort);
262 flow.setActions(actions);
263 status = frm.addStaticFlow(flow);
264 logger.debug("Add Flood Egress Flow Programming Status {} for Flow {} on {} / {}",
265 status, flow, ofNode, node);
267 flow = new FlowConfig(existingFlowConfig);
268 List<String> actions = flow.getActions();
269 String outputPort = ActionType.OUTPUT.toString()+"="+tunnelOFPort;
270 if (actions != null && !actions.contains(outputPort)) {
271 actions.add(outputPort);
272 flow.setActions(actions);
274 logger.debug("Flood Egress Flow already exists. Skipping modify for Flow {} on {} / {}",
278 status = frm.modifyStaticFlow(flow);
279 logger.debug("Modify Flood Egress Flow Programming Status {} for Flow {} on {} / {}",
280 status, flow, ofNode, node);
282 } catch (Exception e) {
283 logger.error("Failed to initialize Flow Rules for {}", node, e);
287 private void removeFloodEgressTunnelBridgeRules(Node node, int patchPort, int internalVlan, int tunnelOFPort) {
288 String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
289 if (brNetId == null) {
290 logger.error("Failed to remove Flow Rules for {}", node);
294 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
295 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
296 Set<String> dpids = bridge.getDatapath_id();
297 if (dpids == null || dpids.size() == 0) return;
298 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
299 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
300 String flowName = "TepFlood"+internalVlan;
301 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
302 IForwardingRulesManager.class, "default", this);
303 FlowConfig flow = frm.getStaticFlow(flowName, ofNode);
304 Status status = null;
306 status = frm.removeStaticFlow(flowName, ofNode);
307 logger.debug("Remove Flood Egress Flow Programming Status {} for Flow {} on {} / {}",
308 status, flow, ofNode, node);
311 logger.debug("Flood Egress Flow already removed. Skipping removal for Flow {} on {} / {}",
315 } catch (Exception e) {
316 logger.error("Failed to remove Flow Rules for {}", node, e);
320 private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
321 Interface intf, boolean local) {
322 String networkId = tenantNetworkManager.getNetworkIdForSegmentationId(segmentationId);
323 if (networkId == null) {
324 logger.debug("Tenant Network not found with Segmentation-id {}", segmentationId);
327 int internalVlan = tenantNetworkManager.getInternalVlan(node, networkId);
328 if (internalVlan == 0) {
329 logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
332 Map<String, String> externalIds = intf.getExternal_ids();
333 if (externalIds == null) {
334 logger.error("No external_ids seen in {}", intf);
338 String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
339 if (attachedMac == null) {
340 logger.error("No AttachedMac seen in {}", intf);
343 String patchInt = adminConfigManager.getPatchToIntegration();
345 int patchOFPort = -1;
347 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
348 Map<String, Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
350 for (Table<?> row : intfs.values()) {
351 Interface patchIntf = (Interface)row;
352 if (patchIntf.getName().equalsIgnoreCase(patchInt)) {
353 Set<BigInteger> of_ports = patchIntf.getOfport();
354 if (of_ports == null || of_ports.size() <= 0) {
355 logger.error("Could NOT Identified Patch port {} on {}", patchInt, node);
358 patchOFPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
359 logger.debug("Identified Patch port {} -> OF ({}) on {}", patchInt, patchOFPort, node);
363 if (patchOFPort == -1) {
364 logger.error("Cannot identify {} interface on {}", patchInt, node);
366 for (Table<?> row : intfs.values()) {
367 Interface tunIntf = (Interface)row;
368 if (tunIntf.getName().equals(this.getTunnelName(tunnelType, segmentationId, dst))) {
369 Set<BigInteger> of_ports = tunIntf.getOfport();
370 if (of_ports == null || of_ports.size() <= 0) {
371 logger.warn("Could not Identify Tunnel port {} on {}. Don't panic. It might get converged soon...", tunIntf.getName(), node);
374 int tunnelOFPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
376 if (tunnelOFPort == -1) {
377 logger.warn("Tunnel Port {} on node {}: OFPort = -1 . Don't panic. It might get converged soon...", tunIntf.getName(), node);
380 logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
383 programRemoteEgressTunnelBridgeRules(node, patchOFPort, attachedMac, internalVlan, tunnelOFPort);
385 programLocalIngressTunnelBridgeRules(node, tunnelOFPort, internalVlan, patchOFPort);
386 programFloodEgressTunnelBridgeRules(node, patchOFPort, internalVlan, tunnelOFPort);
391 } catch (Exception e) {
396 private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
397 Interface intf, boolean local) {
398 String networkId = tenantNetworkManager.getNetworkIdForSegmentationId(segmentationId);
399 if (networkId == null) {
400 logger.debug("Tenant Network not found with Segmentation-id {}",segmentationId);
403 int internalVlan = tenantNetworkManager.getInternalVlan(node,networkId);
404 if (internalVlan == 0) {
405 logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
408 Map<String, String> externalIds = intf.getExternal_ids();
409 if (externalIds == null) {
410 logger.error("No external_ids seen in {}", intf);
414 String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
415 if (attachedMac == null) {
416 logger.error("No AttachedMac seen in {}", intf);
419 String patchInt = adminConfigManager.getPatchToIntegration();
421 int patchOFPort = -1;
423 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
424 Map<String, Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
426 for (Table<?> row : intfs.values()) {
427 Interface patchIntf = (Interface)row;
428 if (patchIntf.getName().equalsIgnoreCase(patchInt)) {
429 Set<BigInteger> of_ports = patchIntf.getOfport();
430 if (of_ports == null || of_ports.size() <= 0) {
431 logger.error("Could NOT Identified Patch port {} on {}", patchInt, node);
434 patchOFPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
435 logger.debug("Identified Patch port {} -> OF ({}) on {}", patchInt, patchOFPort, node);
439 if (patchOFPort == -1) {
440 logger.error("Cannot identify {} interface on {}", patchInt, node);
442 for (Table<?> row : intfs.values()) {
443 Interface tunIntf = (Interface)row;
444 if (tunIntf.getName().equals(this.getTunnelName(tunnelType, segmentationId, dst))) {
445 Set<BigInteger> of_ports = tunIntf.getOfport();
446 if (of_ports == null || of_ports.size() <= 0) {
447 logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
450 int tunnelOFPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
452 if (tunnelOFPort == -1) {
453 logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
456 logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
459 removeRemoteEgressTunnelBridgeRules(node, patchOFPort, attachedMac, internalVlan, tunnelOFPort);
461 removeLocalIngressTunnelBridgeRules(node, tunnelOFPort, internalVlan, patchOFPort);
462 removeFloodEgressTunnelBridgeRules(node, patchOFPort, internalVlan, tunnelOFPort);
467 } catch (Exception e) {
472 private String getIntModVlanFlowName (int inOFPort, String fromVlan, String toVlan) {
473 return "int_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan;
476 private String getIntDropFlowName (int inOFPort) {
477 return "int_drop_"+inOFPort;
480 private String getNetModVlanFlowName (int inOFPort, String fromVlan, String toVlan) {
481 return "net_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan;
484 private String getNetDropFlowName (int inOFPort) {
485 return "net_drop_"+inOFPort;
488 private String getNetFwdFlowName (int inOFPort, int outOFPort, String vlan) {
489 return "net_fwd_"+vlan+"_"+inOFPort+"_"+outOFPort;
492 private void deleteRule (Node node, Node ofNode, String flowName) {
493 logger.debug("deleteRule: node: {} / {}, flowName: {}", node, ofNode, flowName);
496 this.deleteStaticFlow(ofNode, flowName);
497 } catch (Exception e) {
498 logger.error("deleteRule: Failed to delete Flow Rule for {} / {}", node, ofNode, e);
502 /* in_port=p actions=drop */
503 private void programDropRule (Node node, Node ofNode, int inOFPort, String flowName) {
504 logger.debug("programDropRule: node: {} / {}, inOfPort: {}, flowName: {}",
505 node, ofNode, inOFPort, flowName);
508 FlowConfig flow = new FlowConfig();
509 flow.setName(flowName);
510 flow.setNode(ofNode);
511 flow.setInstallInHw(true);
512 flow.setPriority(DROP_FLOW_PRIORITY+"");
513 flow.setIngressPort(inOFPort+"");
514 List<String> actions = new ArrayList<String>();
515 actions.add(ActionType.DROP+"");
516 flow.setActions(actions);
517 Status status = this.addStaticFlow(ofNode, flow);
518 logger.debug("programDropRule: Flow Programming Status {} for Flow {} on {} / {}",
519 status, flow, node, ofNode);
520 } catch (Exception e) {
521 logger.error("programDropRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e);
525 /* in_port=p2,dl_vlan=v actions=mod_vlan_vid,[NORMAL|output:p2] */
526 private void programModVlanRule (Node node, Node ofNode, int inOFPort, int outOFPort, String fromVlan,
527 String toVlan, String flowName) {
528 logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, fromVlan: {}, toVlan: {}, flowName: {}",
529 node, ofNode, inOFPort, fromVlan, toVlan, flowName);
532 FlowConfig flow = new FlowConfig();
533 flow.setName(flowName);
534 flow.setNode(ofNode);
535 flow.setInstallInHw(true);
536 flow.setPriority(INGRESS_TUNNEL_FLOW_PRIORITY+"");
537 flow.setIngressPort(inOFPort+"");
538 flow.setVlanId(fromVlan);
539 List<String> actions = new ArrayList<String>();
540 actions.add(ActionType.SET_VLAN_ID+"="+toVlan);
541 if (outOFPort == -1) {
542 actions.add(ActionType.HW_PATH.toString());
544 actions.add(ActionType.OUTPUT.toString()+"="+outOFPort);
546 flow.setActions(actions);
547 Status status = this.addStaticFlow(ofNode, flow);
548 logger.debug("programModVlanRule: Flow Programming Status {} for Flow {} on {} / {}",
549 status, flow, node, ofNode);
550 } catch (Exception e) {
551 logger.error("programModVlanRule: Failed to initialize Flow Rule for {} / {}", node, ofNode, e);
555 /* in_port=p1,dl_vlan=v actions=output:p2 */
556 private void programForwardRule (Node node, Node ofNode, int inOFPort, int outOFPort, String vlan, String flowName) {
557 logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, outOFPort: {}, flowName: {}",
558 node, ofNode, inOFPort, outOFPort, flowName);
561 FlowConfig flow = new FlowConfig();
562 flow.setName(flowName);
563 flow.setNode(ofNode);
564 flow.setInstallInHw(true);
565 flow.setPriority(EGRESS_TUNNEL_FLOW_PRIORITY + "");
566 flow.setIngressPort(inOFPort + "");
567 flow.setVlanId(vlan);
568 List<String> actions = new ArrayList<String>();
569 actions.add(ActionType.OUTPUT.toString()+"="+outOFPort);
570 flow.setActions(actions);
571 Status status = this.addStaticFlow(ofNode, flow);
572 logger.debug("programForwardRule: Flow Programming Status {} for Flow {} on {} / {}",
573 status, flow, node, ofNode);
574 } catch (Exception e) {
575 logger.error("programForwardRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e);
579 public int getOFPort (Node node, String portName) {
582 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
583 Map<String, Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
585 for (Table<?> row : intfs.values()) {
586 Interface intf = (Interface)row;
587 if (intf.getName().equalsIgnoreCase(portName)) {
588 Set<BigInteger> of_ports = intf.getOfport();
589 if (of_ports == null || of_ports.size() <= 0) {
590 logger.error("Could not identify patch port {} on {}", portName, node);
593 ofPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
594 logger.debug("Identified port {} -> OF ({}) on {}", portName, ofPort, node);
599 } catch (Exception e) {
607 * Transient class to return all the vlan network data needed for flow programming.
609 public class vlanNet {
610 public int patchIntOfPort;
611 public int patchNetOfPort;
612 public int physicalOfPort;
613 public int internalVlan;
615 public vlanNet (NeutronNetwork network, Node node, Interface intf) {
621 initializeVlanNet(network, node, intf);
624 public boolean isValid () {
625 if ((patchIntOfPort != -1) && (patchNetOfPort != -1) && (physicalOfPort != -1) && (internalVlan != -1)) {
632 public int getPatchIntOfPort () {
633 return patchIntOfPort;
636 public int getPatchNetOfPort () {
637 return patchNetOfPort;
640 public int getphysicalOfPort () {
641 return physicalOfPort;
644 public int getInternalVlan () {
648 public void initializeVlanNet (NeutronNetwork network, Node node, Interface intf) {
649 internalVlan = tenantNetworkManager.getInternalVlan(node, network.getNetworkUUID());
650 if (internalVlan == 0) {
651 logger.debug("No InternalVlan provisioned for Tenant Network {}", network.getNetworkUUID());
655 /* Get ofports for patch ports and physical interface. */
656 String patchToNetworkName = adminConfigManager.getPatchToNetwork();
657 String patchToIntegrationName = adminConfigManager.getPatchToIntegration();
658 String physNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
660 patchIntOfPort = getOFPort(node, patchToNetworkName);
661 if (patchIntOfPort == -1) {
662 logger.error("Cannot identify {} interface on {}", patchToNetworkName, node);
666 patchNetOfPort = getOFPort(node, patchToIntegrationName);
667 if (patchNetOfPort == -1) {
668 logger.error("Cannot identify {} interface on {}", patchToIntegrationName, node);
672 physicalOfPort = getOFPort(node, physNetName);
673 if (physicalOfPort == -1) {
674 logger.error("Cannot identify {} interface on {}", physNetName, node);
680 private Node getOFNode (Node node, String bridgeName) {
681 String brUUID = internalNetworkManager.getInternalBridgeUUID(node, bridgeName);
682 if (brUUID == null) {
683 logger.error("getOFNode: Unable to find {} UUID on node {}", bridgeName, node);
688 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
689 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brUUID);
690 Set<String> dpids = bridge.getDatapath_id();
691 if (dpids == null || dpids.size() == 0) {
694 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
695 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
697 } catch (Exception e) {
698 logger.error("deleteRule: Failed to delete Flow Rule for {}", node, e);
705 * Vlan isolation uses a patch port between br-int and br-net. Anything received on one end of
706 * the patch is piped to the other end of the patch so the incoming packets from the network would
707 * arrive untouched at the patch port on br-int.
709 * Program OF1.0 Flow rules on br-net in the ingress direction from the network
710 * and egress direction towards the network.
711 * The logic is to simply match on the incoming patch OF-Port and internal vlan,
712 * rewrite the internal vlan to the external vlan and forward out the physical port.
713 * There is also a flow to match the externally tagged packets from the physical port
714 * rewrite the external tag to the internal tag and forward to the patch port.
716 * priority=100,in_port=1,dl_vlan=1 actions=mod_vlan_vid:2001,output:2
717 * priority=100,in_port=2,dl_vlan=2001 actions=mod_vlan_vid:1actions=output:1
720 private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
721 vlanNet vlanNet = new vlanNet(network, node, intf);
722 if (vlanNet.isValid()) {
723 String netBrName = adminConfigManager.getNetworkBridgeName();
724 String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"");
725 String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID());
727 Node netOFNode = getOFNode(node, netBrName);
728 if (netOFNode == null) {
729 logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node);
733 /* Program flows on br-net */
734 deleteRule(node, netOFNode, "NORMAL");
735 programModVlanRule(node, netOFNode, vlanNet.getPatchNetOfPort(), vlanNet.getphysicalOfPort(),
736 vlanNet.getInternalVlan()+"", network.getProviderSegmentationID(), intModVlanFlowName);
737 programModVlanRule(node, netOFNode, vlanNet.getphysicalOfPort(), vlanNet.getPatchNetOfPort(),
738 network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"", netModVlanFlowName);
742 private void removeVlanRules (NeutronNetwork network, Node node, Interface intf) {
743 vlanNet vlanNet = new vlanNet(network, node, intf);
744 if (vlanNet.isValid()) {
745 String netBrName = adminConfigManager.getNetworkBridgeName();
746 String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"");
747 String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID());
749 Node netOFNode = getOFNode(node, netBrName);
750 if (netOFNode == null) {
751 logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node);
755 deleteRule(node, netOFNode, intModVlanFlowName);
756 deleteRule(node, netOFNode, netModVlanFlowName);
761 public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) {
762 logger.debug("handleInterfaceUpdate: networkType: {}, segmentationId: {}, srcNode: {}, intf: {}",
763 network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf.getName());
765 if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
766 Status status = getVlanReadinessStatus(srcNode, network.getProviderSegmentationID());
767 if (!status.isSuccess()) {
770 this.programVlanRules(network, srcNode, intf);
771 return new Status(StatusCode.SUCCESS);
773 } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
774 network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
775 Status status = getTunnelReadinessStatus(srcNode, network.getProviderSegmentationID());
776 if (!status.isSuccess()) return status;
778 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
779 List<Node> nodes = connectionService.getNodes();
780 nodes.remove(srcNode);
781 for (Node dstNode : nodes) {
782 status = getTunnelReadinessStatus(dstNode, network.getProviderSegmentationID());
783 if (!status.isSuccess()) continue;
784 InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
785 InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
786 status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst, network.getProviderSegmentationID());
787 if (status.isSuccess()) {
788 this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
790 addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src, network.getProviderSegmentationID());
791 if (status.isSuccess()) {
792 this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
795 return new Status(StatusCode.SUCCESS);
797 return new Status(StatusCode.BADREQUEST);
802 public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf, boolean isLastInstanceOnNode) {
803 Status status = new Status(StatusCode.SUCCESS);
804 logger.debug("handleInterfaceDelete: srcNode: {}, networkType: {}, intf: {}, type: {}, isLast: {}",
805 srcNode, (network != null) ? network.getProviderNetworkType() : "",
806 intf.getName(), intf.getType(), isLastInstanceOnNode);
808 if ((network != null) && network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
809 if (isLastInstanceOnNode) {
810 this.removeVlanRules(network, srcNode, intf);
812 } else if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
813 /* Delete tunnel port */
815 OvsDBMap<String, String> options = intf.getOptions();
816 InetAddress src = InetAddress.getByName(options.get("local_ip"));
817 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
818 String key = options.get("key");
819 status = deleteTunnelPort(srcNode, intf.getType(), src, dst, key);
820 } catch (Exception e) {
821 logger.error(e.getMessage(), e);
824 /* delete all other interfaces */
825 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
826 List<Node> nodes = connectionService.getNodes();
827 nodes.remove(srcNode);
828 for (Node dstNode : nodes) {
829 InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
830 InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
831 this.removeTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
832 if (isLastInstanceOnNode) {
833 status = deleteTunnelPort(srcNode, network.getProviderNetworkType(), src, dst, network.getProviderSegmentationID());
835 this.removeTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
836 if (status.isSuccess() && isLastInstanceOnNode) {
837 deleteTunnelPort(dstNode, network.getProviderNetworkType(), dst, src, network.getProviderSegmentationID());
845 private String getTunnelName(String tunnelType, String key, InetAddress dst) {
846 return tunnelType+"-"+key+"-"+dst.getHostAddress();
849 private Interface getTunnelInterface (Node node, String tunnelType, InetAddress dst, String key) {
851 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
852 String portName = getTunnelName(tunnelType, key, dst);
854 Map<String, Table<?>> tunIntfs = ovsdbTable.getRows(node, Interface.NAME.getName());
855 if (tunIntfs != null) {
856 for (Table<?> row : tunIntfs.values()) {
857 Interface tunIntf = (Interface)row;
858 if (tunIntf.getName().equals(portName)) return tunIntf;
862 } catch (Exception e) {
868 private boolean isTunnelPresent(Node node, String tunnelName, String bridgeUUID) throws Exception {
869 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
870 Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
871 if (bridge != null) {
872 Set<UUID> ports = bridge.getPorts();
873 for (UUID portUUID : ports) {
874 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
875 if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return true;
881 private String getTunnelPortUuid(Node node, String tunnelName, String bridgeUUID) throws Exception {
882 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
883 Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
884 if (bridge != null) {
885 Set<UUID> ports = bridge.getPorts();
886 for (UUID portUUID : ports) {
887 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
888 if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return portUUID.toString();
894 private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) {
896 String bridgeUUID = null;
897 String tunnelBridgeName = adminConfigManager.getNetworkBridgeName();
898 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
899 Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
900 if (bridgeTable != null) {
901 for (String uuid : bridgeTable.keySet()) {
902 Bridge bridge = (Bridge)bridgeTable.get(uuid);
903 if (bridge.getName().equals(tunnelBridgeName)) {
909 if (bridgeUUID == null) {
910 logger.error("Could not find Bridge {} in {}", tunnelBridgeName, node);
911 return new Status(StatusCode.NOTFOUND, "Could not find "+tunnelBridgeName+" in "+node);
913 String portName = getTunnelName(tunnelType, key, dst);
915 if (this.isTunnelPresent(node, portName, bridgeUUID)) {
916 logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node);
917 return new Status(StatusCode.SUCCESS);
920 Port tunnelPort = new Port();
921 tunnelPort.setName(portName);
922 StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, tunnelPort);
923 if (!statusWithUuid.isSuccess()) {
924 logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID);
925 return statusWithUuid;
928 String tunnelPortUUID = statusWithUuid.getUuid().toString();
929 String interfaceUUID = null;
931 while ((interfaceUUID == null) && (timeout > 0)) {
932 tunnelPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), tunnelPortUUID);
933 OvsDBSet<UUID> interfaces = tunnelPort.getInterfaces();
934 if (interfaces == null || interfaces.size() == 0) {
935 // Wait for the OVSDB update to sync up the Local cache.
940 interfaceUUID = interfaces.toArray()[0].toString();
941 Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), interfaceUUID);
942 if (intf == null) interfaceUUID = null;
945 if (interfaceUUID == null) {
946 logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID);
947 return new Status(StatusCode.INTERNALERROR);
950 Interface tunInterface = new Interface();
951 tunInterface.setType(tunnelType);
952 OvsDBMap<String, String> options = new OvsDBMap<String, String>();
953 options.put("key", key);
954 options.put("local_ip", src.getHostAddress());
955 options.put("remote_ip", dst.getHostAddress());
956 tunInterface.setOptions(options);
957 Status status = ovsdbTable.updateRow(node, Interface.NAME.getName(), tunnelPortUUID, interfaceUUID, tunInterface);
958 logger.debug("Tunnel {} add status : {}", tunInterface, status);
960 } catch (Exception e) {
961 logger.error("Exception in addTunnelPort", e);
962 return new Status(StatusCode.INTERNALERROR);
966 private Status deleteTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) {
968 String bridgeUUID = null;
969 String tunnelBridgeName = adminConfigManager.getNetworkBridgeName();
970 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
971 Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
972 if (bridgeTable != null) {
973 for (String uuid : bridgeTable.keySet()) {
974 Bridge bridge = (Bridge)bridgeTable.get(uuid);
975 if (bridge.getName().equals(tunnelBridgeName)) {
981 if (bridgeUUID == null) {
982 logger.debug("Could not find Bridge {} in {}", tunnelBridgeName, node);
983 return new Status(StatusCode.SUCCESS);
985 String portName = getTunnelName(tunnelType, key, dst);
986 String tunnelPortUUID = this.getTunnelPortUuid(node, portName, bridgeUUID);
987 Status status = ovsdbTable.deleteRow(node, Port.NAME.getName(), tunnelPortUUID);
988 if (!status.isSuccess()) {
989 logger.error("Failed to delete Tunnel port {} in {} status : {}", portName, bridgeUUID, status);
993 logger.debug("Tunnel {} delete status : {}", portName, status);
995 } catch (Exception e) {
996 logger.error("Exception in deleteTunnelPort", e);
997 return new Status(StatusCode.INTERNALERROR);
1002 public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
1003 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
1004 List<Node> nodes = connectionService.getNodes();
1005 for (Node srcNode : nodes) {
1006 this.handleInterfaceUpdate(null, srcNode, null);
1008 return new Status(StatusCode.SUCCESS);
1012 public void initializeFlowRules(Node node) {
1013 this.initializeFlowRules(node, adminConfigManager.getIntegrationBridgeName());
1014 this.initializeFlowRules(node, adminConfigManager.getExternalBridgeName());
1017 private void initializeFlowRules(Node node, String bridgeName) {
1018 String brIntId = this.getInternalBridgeUUID(node, bridgeName);
1019 if (brIntId == null) {
1020 if (bridgeName == adminConfigManager.getExternalBridgeName()){
1021 logger.debug("Failed to initialize Flow Rules for bridge {} on node {}. Is the Neutron L3 agent running on this node?");
1024 logger.debug("Failed to initialize Flow Rules for bridge {} on node {}", bridgeName, node);
1030 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
1031 Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
1032 Set<String> dpids = bridge.getDatapath_id();
1033 if (dpids == null || dpids.size() == 0) return;
1034 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
1035 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
1036 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, "default", this);
1037 List<Switch> nodes = switchManager.getNetworkDevices();
1038 if (nodes == null) {
1039 logger.debug("No OF nodes learned yet in {}", node);
1042 for (Switch device : nodes) {
1043 if (device.getNode().equals(ofNode)) {
1044 logger.debug("Initialize OF Flows on {}", ofNode);
1045 initializeNormalFlowRules(ofNode);
1049 logger.debug("Could not identify OF node {} for bridge {} in {}", ofNode.toString(), bridgeName, node.toString());
1050 } catch (Exception e) {
1051 logger.error("Failed to initialize Flow Rules for "+node.toString(), e);
1056 public void initializeOFFlowRules(Node openflowNode) {
1057 this.initializeNormalFlowRules(openflowNode);
1058 this.initializeLLDPFlowRules(openflowNode);
1061 private void initializeNormalFlowRules(Node ofNode) {
1062 String flowName = ActionType.HW_PATH.toString();
1063 FlowConfig flow = new FlowConfig();
1064 flow.setName("NORMAL");
1065 flow.setNode(ofNode);
1066 flow.setPriority(NORMAL_PRIORITY+"");
1067 flow.setInstallInHw(true);
1068 List<String> normalAction = new ArrayList<String>();
1069 normalAction.add(flowName);
1070 flow.setActions(normalAction);
1071 Status status = this.addStaticFlow(ofNode, flow);
1072 logger.debug("Flow Programming Add Status {} for Flow {} on {}", status, flow, ofNode);
1075 private void initializeLLDPFlowRules(Node ofNode) {
1076 String flowName = "PuntLLDP";
1077 List<String> puntAction = new ArrayList<String>();
1078 puntAction.add(ActionType.CONTROLLER.toString());
1080 FlowConfig allowLLDP = new FlowConfig();
1081 allowLLDP.setName(flowName);
1082 allowLLDP.setPriority(LLDP_PRIORITY+"");
1083 allowLLDP.setNode(ofNode);
1084 allowLLDP.setInstallInHw(true);
1085 allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue()).toUpperCase());
1086 allowLLDP.setActions(puntAction);
1087 Status status = this.addStaticFlow(ofNode, allowLLDP);
1088 logger.debug("LLDP Flow Add Status {} for Flow {} on {}", status, allowLLDP, ofNode);
1091 private Status addStaticFlow (Node ofNode, FlowConfig flowConfig) {
1092 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
1093 IForwardingRulesManager.class, "default", this);
1094 String flowName = flowConfig.getName();
1095 if (frm.getStaticFlow(flowName, ofNode) != null) {
1096 logger.debug("Flow already exists {} on {}. Skipping installation.", flowName, ofNode);
1097 return new Status(StatusCode.CONFLICT, "Flow with name "+flowName+" exists in node "+ofNode.toString());
1099 return frm.addStaticFlow(flowConfig);
1102 private Status deleteStaticFlow (Node ofNode, String flowName) {
1103 IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
1104 IForwardingRulesManager.class, "default", this);
1105 if (frm.getStaticFlow(flowName, ofNode) == null) {
1106 logger.debug("Flow does not exist {} on {}. Skipping deletion.", flowName, ofNode);
1107 return new Status(StatusCode.SUCCESS);
1109 return frm.removeStaticFlow(flowName,ofNode);
1112 private String getInternalBridgeUUID (Node node, String bridgeName) {
1114 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
1115 Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
1116 if (bridgeTable == null) return null;
1117 for (String key : bridgeTable.keySet()) {
1118 Bridge bridge = (Bridge)bridgeTable.get(key);
1119 if (bridge.getName().equals(bridgeName)) return key;
1121 } catch (Exception e) {
1122 logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);