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, Dave Tucker
10 package org.opendaylight.ovsdb.openstack.netvirt.providers;
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.CheckedFuture;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
16 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
21 import org.opendaylight.controller.sal.core.Node;
22 import org.opendaylight.controller.sal.utils.HexEncode;
23 import org.opendaylight.controller.sal.utils.Status;
24 import org.opendaylight.controller.sal.utils.StatusCode;
25 import org.opendaylight.ovsdb.lib.notation.Row;
26 import org.opendaylight.ovsdb.lib.notation.UUID;
27 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
28 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
29 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
30 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
31 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
32 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
34 import org.opendaylight.ovsdb.openstack.netvirt.providers.mdsalopenflow13.OF13MdSalInstruction;
35 import org.opendaylight.ovsdb.openstack.netvirt.providers.mdsalopenflow13.OF13MdSalMatch;
36 import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
37 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
38 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
39 import org.opendaylight.ovsdb.schema.openvswitch.Port;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
86 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
88 import com.google.common.base.Preconditions;
89 import com.google.common.collect.Lists;
90 import com.google.common.collect.Maps;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
94 import java.math.BigInteger;
95 import java.net.InetAddress;
96 import java.util.List;
99 import java.util.concurrent.ExecutionException;
102 * Open vSwitch OpenFlow 1.3 Networking Provider for OpenStack Neutron
104 public class OF13Provider implements NetworkingProvider {
105 private static final Logger logger = LoggerFactory.getLogger(OF13Provider.class);
106 private DataBroker dataBroker;
107 private static final short TABLE_0_DEFAULT_INGRESS = 0;
108 private static final short TABLE_1_ISOLATE_TENANT = 10;
109 private static final short TABLE_2_LOCAL_FORWARD = 20;
110 private static final String OPENFLOW = "openflow:";
111 private static Long groupId = 1L;
113 private volatile org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService configurationService;
114 private volatile BridgeConfigurationManager bridgeConfigurationManager;
115 private volatile TenantNetworkManager tenantNetworkManager;
116 private volatile OvsdbConfigurationService ovsdbConfigurationService;
117 private volatile OvsdbConnectionService connectionService;
118 private volatile MdsalConsumer mdsalConsumer;
120 public OF13Provider(){
125 public boolean hasPerTenantTunneling() {
129 private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
130 InetAddress srcTunnelEndPoint = configurationService.getTunnelEndPoint(node);
131 if (srcTunnelEndPoint == null) {
132 logger.error("Tunnel Endpoint not configured for Node {}", node);
133 return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
136 if (!bridgeConfigurationManager.isNodeNeutronReady(node)) {
137 logger.error(node+" is not Overlay ready");
138 return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
141 if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
142 logger.debug(node+" has no VM corresponding to segment "+ tunnelKey);
143 return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey);
145 return new Status(StatusCode.SUCCESS);
148 private String getTunnelName(String tunnelType, InetAddress dst) {
149 return tunnelType+"-"+dst.getHostAddress();
152 private boolean isTunnelPresent(Node node, String tunnelName, String bridgeUUID) throws Exception {
153 Preconditions.checkNotNull(ovsdbConfigurationService);
154 Row bridgeRow = ovsdbConfigurationService
155 .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUUID);
156 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
157 if (bridge != null) {
158 Set<UUID> ports = bridge.getPortsColumn().getData();
159 for (UUID portUUID : ports) {
160 Row portRow = ovsdbConfigurationService
161 .getRow(node, ovsdbConfigurationService.getTableName(node, Port.class), portUUID.toString());
162 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
163 if (port != null && tunnelName.equalsIgnoreCase(port.getName())) return true;
169 private String getPortUuid(Node node, String name, String bridgeUUID) throws Exception {
170 Preconditions.checkNotNull(ovsdbConfigurationService);
171 Row bridgeRow = ovsdbConfigurationService
172 .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUUID);
173 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
174 if (bridge != null) {
175 Set<UUID> ports = bridge.getPortsColumn().getData();
176 for (UUID portUUID : ports) {
177 Row portRow = ovsdbConfigurationService
178 .getRow(node, ovsdbConfigurationService.getTableName(node, Port.class), portUUID.toString());
179 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
180 if (port != null && name.equalsIgnoreCase(port.getName())) return portUUID.toString();
186 private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
187 Preconditions.checkNotNull(ovsdbConfigurationService);
189 String bridgeUUID = null;
190 String tunnelBridgeName = configurationService.getIntegrationBridgeName();
191 Map<String, Row> bridgeTable = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
192 if (bridgeTable != null) {
193 for (String uuid : bridgeTable.keySet()) {
194 Bridge bridge = ovsdbConfigurationService.getTypedRow(node,Bridge.class, bridgeTable.get(uuid));
195 if (bridge.getName().equals(tunnelBridgeName)) {
201 if (bridgeUUID == null) {
202 logger.error("Could not find Bridge {} in {}", tunnelBridgeName, node);
203 return new Status(StatusCode.NOTFOUND, "Could not find "+tunnelBridgeName+" in "+node);
205 String portName = getTunnelName(tunnelType, dst);
207 if (this.isTunnelPresent(node, portName, bridgeUUID)) {
208 logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node);
209 return new Status(StatusCode.SUCCESS);
212 Port tunnelPort = ovsdbConfigurationService.createTypedRow(node, Port.class);
213 tunnelPort.setName(portName);
214 StatusWithUuid statusWithUuid = ovsdbConfigurationService
215 .insertRow(node, ovsdbConfigurationService.getTableName(node, Port.class), bridgeUUID, tunnelPort.getRow());
216 if (!statusWithUuid.isSuccess()) {
217 logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID);
218 return statusWithUuid;
221 String tunnelPortUUID = statusWithUuid.getUuid().toString();
222 String interfaceUUID = null;
224 while ((interfaceUUID == null) && (timeout > 0)) {
225 Row portRow = ovsdbConfigurationService
226 .getRow(node, ovsdbConfigurationService.getTableName(node, Port.class), tunnelPortUUID);
227 tunnelPort = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
228 Set<UUID> interfaces = tunnelPort.getInterfacesColumn().getData();
229 if (interfaces == null || interfaces.size() == 0) {
230 // Wait for the OVSDB update to sync up the Local cache.
235 interfaceUUID = interfaces.toArray()[0].toString();
236 Row intfRow = ovsdbConfigurationService
237 .getRow(node, ovsdbConfigurationService.getTableName(node, Interface.class), interfaceUUID);
238 Interface intf = ovsdbConfigurationService.getTypedRow(node, Interface.class, intfRow);
239 if (intf == null) interfaceUUID = null;
242 if (interfaceUUID == null) {
243 logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID);
244 return new Status(StatusCode.INTERNALERROR);
247 Interface tunInterface = ovsdbConfigurationService.createTypedRow(node, Interface.class);
248 tunInterface.setType(tunnelType);
249 Map<String, String> options = Maps.newHashMap();
250 options.put("key", "flow");
251 options.put("local_ip", src.getHostAddress());
252 options.put("remote_ip", dst.getHostAddress());
253 tunInterface.setOptions(options);
254 Status status = ovsdbConfigurationService
255 .updateRow(node, ovsdbConfigurationService.getTableName(node, Interface.class), tunnelPortUUID, interfaceUUID, tunInterface.getRow());
256 logger.debug("Tunnel {} add status : {}", tunInterface, status);
258 } catch (Exception e) {
259 logger.error("Exception in addTunnelPort", e);
260 return new Status(StatusCode.INTERNALERROR);
264 /* delete port from ovsdb port table */
265 private Status deletePort(Node node, String bridgeName, String portName) {
266 Preconditions.checkNotNull(ovsdbConfigurationService);
268 String bridgeUUID = null;
269 Map<String, Row> bridgeTable = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
270 if (bridgeTable != null) {
271 for (String uuid : bridgeTable.keySet()) {
272 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(uuid));
273 if (bridge.getName().equals(bridgeName)) {
279 if (bridgeUUID == null) {
280 logger.debug("Could not find Bridge {} in {}", bridgeName, node);
281 return new Status(StatusCode.SUCCESS);
284 String portUUID = this.getPortUuid(node, portName, bridgeUUID);
285 Status status = new Status(StatusCode.SUCCESS);
286 if (portUUID != null) {
287 status = ovsdbConfigurationService
288 .deleteRow(node, ovsdbConfigurationService.getTableName(node, Port.class), portUUID);
289 if (!status.isSuccess()) {
290 logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID,
294 logger.debug("Port {} delete status : {}", portName, status);
297 } catch (Exception e) {
298 logger.error("Exception in deletePort", e);
299 return new Status(StatusCode.INTERNALERROR);
303 private Status deleteTunnelPort(Node node, String tunnelType, InetAddress src, InetAddress dst) {
304 String tunnelBridgeName = configurationService.getIntegrationBridgeName();
305 String portName = getTunnelName(tunnelType, dst);
306 return deletePort(node, tunnelBridgeName, portName);
309 private Status deletePhysicalPort(Node node, String phyIntfName) {
310 String intBridgeName = configurationService.getIntegrationBridgeName();
311 return deletePort(node, intBridgeName, phyIntfName);
314 private void programLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
318 * Match: VM sMac and Local Ingress Port
319 * Action:Action: Set Tunnel ID and GOTO Local Table (5)
322 handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, true);
327 * Match: Drop any remaining Ingress Local VM Packets
328 * Action: Drop w/ a low priority
331 handleDropSrcIface(dpid, localPort, true);
336 * Match: Match TunID and Destination DL/dMAC Addr
337 * Action: Output Port
338 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
341 handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, true);
346 * Match: Tunnel ID and dMAC (::::FF:FF)
347 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
348 * actions=output:2,3,4,5
351 handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
354 * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
359 * Match: Any remaining Ingress Local VM Packets
360 * Action: Drop w/ a low priority
361 * -------------------------------------------
362 * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
365 handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, true);
370 * Match: Any Remaining Flows w/a TunID
371 * Action: Drop w/ a low priority
372 * table=2,priority=8192,tun_id=0x5 actions=drop
375 handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, true);
378 private void removeLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
382 * Match: VM sMac and Local Ingress Port
383 * Action:Action: Set Tunnel ID and GOTO Local Table (5)
386 handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, false);
391 * Match: Drop any remaining Ingress Local VM Packets
392 * Action: Drop w/ a low priority
395 handleDropSrcIface(dpid, localPort, false);
400 * Match: Match TunID and Destination DL/dMAC Addr
401 * Action: Output Port
402 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
405 handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, false);
410 * Match: Tunnel ID and dMAC (::::FF:FF)
411 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
412 * actions=output:2,3,4,5
415 handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
418 private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
422 * Match: Ingress Port, Tunnel ID
423 * Action: GOTO Local Table (20)
426 handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
431 * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
432 * Action: Flood to selected destination TEPs
433 * -------------------------------------------
434 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
435 * actions=output:10,output:11,goto_table:2
438 handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
442 private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
446 * Match: Drop any remaining Ingress Local VM Packets
447 * Action: Drop w/ a low priority
448 * -------------------------------------------
449 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
450 * actions=output:11,goto_table:2
453 handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, true);
456 private void removeRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
460 * Match: Drop any remaining Ingress Local VM Packets
461 * Action: Drop w/ a low priority
462 * -------------------------------------------
463 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
464 * actions=output:11,goto_table:2
467 handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, false);
470 /* Remove tunnel rules if last node in this tenant network */
471 private void removePerTunnelRules(Node node, Long dpid, String segmentationId, long tunnelOFPort) {
473 * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
478 * Match: Any remaining Ingress Local VM Packets
479 * Action: Drop w/ a low priority
480 * -------------------------------------------
481 * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
484 handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, false);
489 * Match: Any Remaining Flows w/a TunID
490 * Action: Drop w/ a low priority
491 * table=2,priority=8192,tun_id=0x5 actions=drop
494 handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
499 * Match: Ingress Port, Tunnel ID
500 * Action: GOTO Local Table (10)
503 handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
508 * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
509 * Action: Flood to selected destination TEPs
510 * -------------------------------------------
511 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
512 * actions=output:10,output:11,goto_table:2
515 handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
518 private void programLocalVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
522 * Match: VM sMac and Local Ingress Port
523 * Action: Set VLAN ID and GOTO Local Table 1
526 handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
527 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
533 * Match: Drop any remaining Ingress Local VM Packets
534 * Action: Drop w/ a low priority
537 handleDropSrcIface(dpid, localPort, true);
542 * Match: Match VLAN ID and Destination DL/dMAC Addr
543 * Action: strip vlan, output to local port
544 * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
547 handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
548 localPort, attachedMac, true);
553 * Match: VLAN ID and dMAC (::::FF:FF)
554 * Action: strip vlan, output to all local ports in this vlan
555 * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
556 * actions= strip_vlan, output:2,3,4,5
559 handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
565 * Match: Any Remaining Flows w/a VLAN ID
566 * Action: Drop w/ a low priority
567 * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
570 handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
574 private void removeLocalVlanRules(Node node, Long dpid,
575 String segmentationId, String attachedMac,
580 * Match: VM sMac and Local Ingress Port
581 * Action: Set VLAN ID and GOTO Local Table 1
584 handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
585 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
591 * Match: Drop any remaining Ingress Local VM Packets
592 * Action: Drop w/ a low priority
595 handleDropSrcIface(dpid, localPort, false);
600 * Match: Match VLAN ID and Destination DL/dMAC Addr
601 * Action: strip vlan, output to local port
602 * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
605 handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
606 localPort, attachedMac, false);
611 * Match: VLAN ID and dMAC (::::FF:FF)
612 * Action: strip vlan, output to all local ports in this vlan
613 * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
614 * actions= strip_vlan, output:2,3,4,5
617 handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
621 private void programLocalIngressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
625 * Match: Ingress port = physical interface, Vlan ID
626 * Action: GOTO Local Table 2
629 handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
630 segmentationId, ethPort, true);
635 * Match: Match VLAN ID and L2 ::::FF:FF Flooding
636 * Action: Flood to local and remote VLAN members
637 * -------------------------------------------
638 * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
639 * actions=output:10 (eth port),goto_table:2
642 handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
643 segmentationId, ethPort, true);
646 private void programRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
650 * Match: Destination MAC is local VM MAC and vlan id
651 * Action: go to table 2
652 * -------------------------------------------
653 * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
654 * actions=goto_table:2
657 handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
658 segmentationId, ethPort, attachedMac, true);
664 * Action: Go to table 2
665 * -------------------------------------------
666 * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
669 handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
670 segmentationId, ethPort, true);
673 private void removeRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
677 * Match: Destination MAC is local VM MAC and vlan id
678 * Action: go to table 2
679 * -------------------------------------------
680 * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
681 * actions=goto_table:2
684 handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
685 segmentationId, ethPort, attachedMac, false);
688 private void removePerVlanRules(Node node, Long dpid, String segmentationId, long ethPort) {
692 * Match: Any Remaining Flows w/a VLAN ID
693 * Action: Drop w/ a low priority
694 * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
697 handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
703 * Match: Ingress port = physical interface, Vlan ID
704 * Action: GOTO Local Table 2
707 handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
708 segmentationId, ethPort, false);
713 * Match: Match VLAN ID and L2 ::::FF:FF Flooding
714 * Action: Flood to local and remote VLAN members
715 * -------------------------------------------
716 * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
717 * actions=output:10 (eth port),goto_table:2
720 handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
721 segmentationId, ethPort, false);
727 * Action: Go to table 2
728 * -------------------------------------------
729 * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
732 handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
733 segmentationId, ethPort, false);
735 private Long getDpid (Node node, String bridgeUuid) {
736 Preconditions.checkNotNull(ovsdbConfigurationService);
738 Row bridgeRow = ovsdbConfigurationService
739 .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUuid);
740 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
741 Set<String> dpids = bridge.getDatapathIdColumn().getData();
742 if (dpids == null || dpids.size() == 0) return 0L;
743 return HexEncode.stringToLong((String) dpids.toArray()[0]);
744 } catch (Exception e) {
745 logger.error("Error finding Bridge's OF DPID", e);
750 private Long getIntegrationBridgeOFDPID (Node node) {
752 String bridgeName = configurationService.getIntegrationBridgeName();
753 String brIntId = this.getInternalBridgeUUID(node, bridgeName);
754 if (brIntId == null) {
755 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
759 return getDpid(node, brIntId);
760 } catch (Exception e) {
761 logger.error("Error finding Integration Bridge's OF DPID", e);
766 private Long getExternalBridgeDpid (Node node) {
768 String bridgeName = configurationService.getExternalBridgeName();
769 String brUuid = this.getInternalBridgeUUID(node, bridgeName);
770 if (brUuid == null) {
771 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
775 return getDpid(node, brUuid);
776 } catch (Exception e) {
777 logger.error("Error finding External Bridge's OF DPID", e);
782 private void programLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
784 Long dpid = this.getIntegrationBridgeOFDPID(node);
786 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
790 Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
791 if (of_ports == null || of_ports.size() <= 0) {
792 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
795 long localPort = (Long)of_ports.toArray()[0];
797 Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
798 if (externalIds == null) {
799 logger.error("No external_ids seen in {}", intf);
803 String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
804 if (attachedMac == null) {
805 logger.error("No AttachedMac seen in {}", intf);
809 /* Program local rules based on network type */
810 if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
811 logger.debug("Program local vlan rules for interface {}", intf.getName());
812 programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
813 } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
814 networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
815 logger.debug("Program local bridge rules for interface {}", intf.getName());
816 programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
818 } catch (Exception e) {
819 logger.error("Exception in programming Local Rules for "+intf+" on "+node, e);
823 private void removeLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
825 Long dpid = this.getIntegrationBridgeOFDPID(node);
827 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
831 Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
832 if (of_ports == null || of_ports.size() <= 0) {
833 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
836 long localPort = (Long)of_ports.toArray()[0];
838 Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
839 if (externalIds == null) {
840 logger.error("No external_ids seen in {}", intf);
844 String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
845 if (attachedMac == null) {
846 logger.error("No AttachedMac seen in {}", intf);
850 /* Program local rules based on network type */
851 if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
852 logger.debug("Remove local vlan rules for interface {}", intf.getName());
853 removeLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
854 } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
855 networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
856 logger.debug("Remove local bridge rules for interface {}", intf.getName());
857 removeLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
859 } catch (Exception e) {
860 logger.error("Exception in removing Local Rules for "+intf+" on "+node, e);
864 private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
865 Interface intf, boolean local) {
867 Preconditions.checkNotNull(ovsdbConfigurationService);
871 Long dpid = this.getIntegrationBridgeOFDPID(node);
873 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
877 Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
878 if (of_ports == null || of_ports.size() <= 0) {
879 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
882 long localPort = (Long)of_ports.toArray()[0];
884 Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
885 if (externalIds == null) {
886 logger.error("No external_ids seen in {}", intf);
890 String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
891 if (attachedMac == null) {
892 logger.error("No AttachedMac seen in {}", intf);
896 Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
898 for (Row row : intfs.values()) {
899 Interface tunIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
900 if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
901 of_ports = tunIntf.getOpenFlowPortColumn().getData();
902 if (of_ports == null || of_ports.size() <= 0) {
903 logger.debug("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
906 long tunnelOFPort = (Long)of_ports.toArray()[0];
908 if (tunnelOFPort == -1) {
909 logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
912 logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
915 programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
917 logger.trace("program local ingress tunnel rules: node" + node.getNodeIDString() + " intf " + intf.getName());
919 programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
925 } catch (Exception e) {
930 private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
931 Interface intf, boolean local, boolean isLastInstanceOnNode) {
933 Preconditions.checkNotNull(ovsdbConfigurationService);
936 Long dpid = this.getIntegrationBridgeOFDPID(node);
938 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
942 Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
943 if (of_ports == null || of_ports.size() <= 0) {
944 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
947 long localPort = (Long)of_ports.toArray()[0];
949 Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
950 if (externalIds == null) {
951 logger.error("No external_ids seen in {}", intf);
955 String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
956 if (attachedMac == null) {
957 logger.error("No AttachedMac seen in {}", intf);
961 Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
963 for (Row row : intfs.values()) {
964 Interface tunIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
965 if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
966 of_ports = tunIntf.getOpenFlowPortColumn().getData();
967 if (of_ports == null || of_ports.size() <= 0) {
968 logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
971 long tunnelOFPort = (Long)of_ports.toArray()[0];
973 if (tunnelOFPort == -1) {
974 logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
977 logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
980 removeRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
982 if (local && isLastInstanceOnNode) {
983 removePerTunnelRules(node, dpid, segmentationId, tunnelOFPort);
989 } catch (Exception e) {
994 private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
995 Preconditions.checkNotNull(ovsdbConfigurationService);
996 logger.debug("Program vlan rules for interface {}", intf.getName());
999 Long dpid = this.getIntegrationBridgeOFDPID(node);
1001 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1005 Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
1007 while ((of_ports == null) && (timeout > 0)) {
1008 of_ports = intf.getOpenFlowPortColumn().getData();
1009 if (of_ports == null || of_ports.size() <= 0) {
1010 // Wait for the OVSDB update to sync up the Local cache.
1015 if (of_ports == null || of_ports.size() <= 0) {
1016 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
1020 Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
1021 if (externalIds == null) {
1022 logger.error("No external_ids seen in {}", intf);
1026 String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
1027 if (attachedMac == null) {
1028 logger.error("No AttachedMac seen in {}", intf);
1032 Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
1033 if (intfs != null) {
1034 for (Row row : intfs.values()) {
1035 Interface ethIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1036 if (ethIntf.getName().equalsIgnoreCase(bridgeConfigurationManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork()))) {
1037 of_ports = ethIntf.getOpenFlowPortColumn().getData();
1039 while ((of_ports == null) && (timeout > 0)) {
1040 of_ports = ethIntf.getOpenFlowPortColumn().getData();
1041 if (of_ports == null || of_ports.size() <= 0) {
1042 // Wait for the OVSDB update to sync up the Local cache.
1048 if (of_ports == null || of_ports.size() <= 0) {
1049 logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
1052 long ethOFPort = (Long)of_ports.toArray()[0];
1054 if (ethOFPort == -1) {
1055 logger.error("Could NOT Identify eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1056 throw new Exception("port number < 0");
1058 logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1060 programRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1061 programLocalIngressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1066 } catch (Exception e) {
1067 logger.error("", e);
1071 private void removeVlanRules (NeutronNetwork network, Node node,
1072 Interface intf, boolean isLastInstanceOnNode) {
1073 Preconditions.checkNotNull(ovsdbConfigurationService);
1074 logger.debug("Remove vlan rules for interface {}", intf.getName());
1078 Long dpid = this.getIntegrationBridgeOFDPID(node);
1080 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1084 Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
1085 if (of_ports == null || of_ports.size() <= 0) {
1086 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
1090 Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
1091 if (externalIds == null) {
1092 logger.error("No external_ids seen in {}", intf);
1096 String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
1097 if (attachedMac == null) {
1098 logger.error("No AttachedMac seen in {}", intf);
1102 Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
1103 if (intfs != null) {
1104 for (Row row : intfs.values()) {
1105 Interface ethIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1106 if (ethIntf.getName().equalsIgnoreCase(bridgeConfigurationManager.getPhysicalInterfaceName(node,
1107 network.getProviderPhysicalNetwork()))) {
1108 of_ports = ethIntf.getOpenFlowPortColumn().getData();
1109 if (of_ports == null || of_ports.size() <= 0) {
1110 logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
1113 long ethOFPort = (Long)of_ports.toArray()[0];
1115 if (ethOFPort == -1) {
1116 logger.error("Could NOT Identify eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1117 throw new Exception("port number < 0");
1119 logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1121 removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1122 if (isLastInstanceOnNode) {
1123 removePerVlanRules(node, dpid, network.getProviderSegmentationID(), ethOFPort);
1129 } catch (Exception e) {
1130 logger.error("", e);
1135 public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) {
1136 Preconditions.checkNotNull(connectionService);
1137 List<Node> nodes = connectionService.getNodes();
1138 nodes.remove(srcNode);
1139 this.programLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf);
1141 if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
1142 this.programVlanRules(network, srcNode, intf);
1143 } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
1144 || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)){
1145 for (Node dstNode : nodes) {
1146 InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1147 InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1148 Status status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst);
1149 if (status.isSuccess()) {
1150 this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
1152 addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
1153 if (status.isSuccess()) {
1154 this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
1159 return new Status(StatusCode.SUCCESS);
1162 private Status triggerInterfaceUpdates(Node node) {
1163 Preconditions.checkNotNull(ovsdbConfigurationService);
1165 Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
1166 if (intfs != null) {
1167 for (Row row : intfs.values()) {
1168 Interface intf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1169 NeutronNetwork network = tenantNetworkManager.getTenantNetwork(intf);
1170 logger.debug("Trigger Interface update for {}", intf);
1171 if (network != null) {
1172 this.handleInterfaceUpdate(network, node, intf);
1176 } catch (Exception e) {
1177 logger.error("Error Triggering the lost interface updates for "+ node, e);
1178 return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage());
1180 return new Status(StatusCode.SUCCESS);
1183 public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
1184 // TODO Auto-generated method stub
1189 public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf,
1190 boolean isLastInstanceOnNode) {
1191 Preconditions.checkNotNull(connectionService);
1192 Status status = new Status(StatusCode.SUCCESS);
1193 List<Node> nodes = connectionService.getNodes();
1194 nodes.remove(srcNode);
1196 logger.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
1197 List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(srcNode);
1198 if (intf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
1199 || intf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
1200 /* Delete tunnel port */
1202 Map<String, String> options = intf.getOptionsColumn().getData();
1203 InetAddress src = InetAddress.getByName(options.get("local_ip"));
1204 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
1205 status = deleteTunnelPort(srcNode, intf.getTypeColumn().getData(), src, dst);
1206 } catch (Exception e) {
1207 logger.error(e.getMessage(), e);
1209 } else if (phyIfName.contains(intf.getName())) {
1210 deletePhysicalPort(srcNode, intf.getName());
1212 /* delete all other interfaces */
1213 this.removeLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(),
1216 if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
1217 this.removeVlanRules(network, srcNode,
1218 intf, isLastInstanceOnNode);
1219 } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
1220 || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
1222 for (Node dstNode : nodes) {
1223 InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1224 InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1225 logger.info("Remove tunnel rules for interface " + intf.getName() + " on srcNode " + srcNode.getNodeIDString());
1226 this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
1227 dst, srcNode, intf, true, isLastInstanceOnNode);
1228 logger.info("Remove tunnel rules for interface " + intf.getName() + " on dstNode " + dstNode.getNodeIDString());
1229 this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
1230 src, dstNode, intf, false, isLastInstanceOnNode);
1238 public void initializeFlowRules(Node node) {
1239 this.initializeFlowRules(node, configurationService.getIntegrationBridgeName());
1240 this.initializeFlowRules(node, configurationService.getExternalBridgeName());
1241 this.triggerInterfaceUpdates(node);
1244 private void initializeFlowRules(Node node, String bridgeName) {
1245 String bridgeUuid = this.getInternalBridgeUUID(node, bridgeName);
1246 if (bridgeUuid == null) {
1250 Long dpid = getDpid(node, bridgeUuid);
1253 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1260 * Match: LLDP (0x88CCL)
1261 * Action: Packet_In to Controller Reserved Port
1264 writeLLDPRule(dpid);
1265 if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1266 writeNormalRule(dpid);
1271 * Create an LLDP Flow Rule to encapsulate into
1272 * a packet_in that is sent to the controller
1273 * for topology handling.
1274 * Match: Ethertype 0x88CCL
1275 * Action: Punt to Controller in a Packet_In msg
1278 private void writeLLDPRule(Long dpidLong) {
1280 String nodeName = OPENFLOW + dpidLong;
1281 EtherType etherType = new EtherType(0x88CCL);
1283 MatchBuilder matchBuilder = new MatchBuilder();
1284 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1285 FlowBuilder flowBuilder = new FlowBuilder();
1287 // Create Match(es) and Set them in the FlowBuilder Object
1288 flowBuilder.setMatch(OF13MdSalMatch.createEtherTypeMatch(matchBuilder, etherType).build());
1290 // Create the OF Actions and Instructions
1291 InstructionBuilder ib = new InstructionBuilder();
1292 InstructionsBuilder isb = new InstructionsBuilder();
1294 // Instructions List Stores Individual Instructions
1295 List<Instruction> instructions = Lists.newArrayList();
1297 // Call the InstructionBuilder Methods Containing Actions
1298 OF13MdSalInstruction.createSendToControllerInstructions(ib);
1300 ib.setKey(new InstructionKey(0));
1301 instructions.add(ib.build());
1303 // Add InstructionBuilder to the Instruction(s)Builder List
1304 isb.setInstruction(instructions);
1306 // Add InstructionsBuilder to FlowBuilder
1307 flowBuilder.setInstructions(isb.build());
1309 String flowId = "LLDP";
1310 flowBuilder.setId(new FlowId(flowId));
1311 FlowKey key = new FlowKey(new FlowId(flowId));
1312 flowBuilder.setBarrier(true);
1313 flowBuilder.setTableId((short) 0);
1314 flowBuilder.setKey(key);
1315 flowBuilder.setFlowName(flowId);
1316 flowBuilder.setHardTimeout(0);
1317 flowBuilder.setIdleTimeout(0);
1318 writeFlow(flowBuilder, nodeBuilder);
1322 * Create a NORMAL Table Miss Flow Rule
1324 * Action: forward to NORMAL pipeline
1327 private void writeNormalRule(Long dpidLong) {
1329 String nodeName = OPENFLOW + dpidLong;
1331 MatchBuilder matchBuilder = new MatchBuilder();
1332 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1333 FlowBuilder flowBuilder = new FlowBuilder();
1335 // Create the OF Actions and Instructions
1336 InstructionBuilder ib = new InstructionBuilder();
1337 InstructionsBuilder isb = new InstructionsBuilder();
1339 // Instructions List Stores Individual Instructions
1340 List<Instruction> instructions = Lists.newArrayList();
1342 // Call the InstructionBuilder Methods Containing Actions
1343 OF13MdSalInstruction.createNormalInstructions(ib);
1345 ib.setKey(new InstructionKey(0));
1346 instructions.add(ib.build());
1348 // Add InstructionBuilder to the Instruction(s)Builder List
1349 isb.setInstruction(instructions);
1351 // Add InstructionsBuilder to FlowBuilder
1352 flowBuilder.setInstructions(isb.build());
1354 String flowId = "NORMAL";
1355 flowBuilder.setId(new FlowId(flowId));
1356 FlowKey key = new FlowKey(new FlowId(flowId));
1357 flowBuilder.setMatch(matchBuilder.build());
1358 flowBuilder.setPriority(0);
1359 flowBuilder.setBarrier(true);
1360 flowBuilder.setTableId((short) 0);
1361 flowBuilder.setKey(key);
1362 flowBuilder.setFlowName(flowId);
1363 flowBuilder.setHardTimeout(0);
1364 flowBuilder.setIdleTimeout(0);
1365 writeFlow(flowBuilder, nodeBuilder);
1369 * (Table:0) Ingress Tunnel Traffic
1370 * Match: OpenFlow InPort and Tunnel ID
1371 * Action: GOTO Local Table (10)
1372 * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
1375 private void handleTunnelIn(Long dpidLong, Short writeTable,
1376 Short goToTableId, String segmentationId,
1377 Long ofPort, boolean write) {
1379 String nodeName = OPENFLOW + dpidLong;
1381 BigInteger tunnelId = new BigInteger(segmentationId);
1382 MatchBuilder matchBuilder = new MatchBuilder();
1383 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1384 FlowBuilder flowBuilder = new FlowBuilder();
1386 // Create Match(es) and Set them in the FlowBuilder Object
1387 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, tunnelId).build());
1388 flowBuilder.setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, ofPort).build());
1391 // Create the OF Actions and Instructions
1392 InstructionBuilder ib = new InstructionBuilder();
1393 InstructionsBuilder isb = new InstructionsBuilder();
1395 // Instructions List Stores Individual Instructions
1396 List<Instruction> instructions = Lists.newArrayList();
1398 // Call the InstructionBuilder Methods Containing Actions
1399 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1401 ib.setKey(new InstructionKey(0));
1402 instructions.add(ib.build());
1404 // Add InstructionBuilder to the Instruction(s)Builder List
1405 isb.setInstruction(instructions);
1407 // Add InstructionsBuilder to FlowBuilder
1408 flowBuilder.setInstructions(isb.build());
1411 String flowId = "TunnelIn_"+segmentationId+"_"+ofPort;
1412 // Add Flow Attributes
1413 flowBuilder.setId(new FlowId(flowId));
1414 FlowKey key = new FlowKey(new FlowId(flowId));
1415 flowBuilder.setStrict(true);
1416 flowBuilder.setBarrier(false);
1417 flowBuilder.setTableId(writeTable);
1418 flowBuilder.setKey(key);
1419 flowBuilder.setFlowName(flowId);
1420 flowBuilder.setHardTimeout(0);
1421 flowBuilder.setIdleTimeout(0);
1424 writeFlow(flowBuilder, nodeBuilder);
1426 removeFlow(flowBuilder, nodeBuilder);
1431 * (Table:0) Ingress VLAN Traffic
1432 * Match: OpenFlow InPort and vlan ID
1433 * Action: GOTO Local Table (20)
1434 * table=0,vlan_id=0x5,in_port=10, actions=goto_table:2
1437 private void handleVlanIn(Long dpidLong, Short writeTable, Short goToTableId,
1438 String segmentationId, Long ethPort, boolean write) {
1440 String nodeName = OPENFLOW + dpidLong;
1442 MatchBuilder matchBuilder = new MatchBuilder();
1443 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1444 FlowBuilder flowBuilder = new FlowBuilder();
1446 // Create Match(es) and Set them in the FlowBuilder Object
1447 flowBuilder.setMatch(
1448 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)))
1450 .setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, ethPort)
1454 // Create the OF Actions and Instructions
1455 InstructionBuilder ib = new InstructionBuilder();
1456 InstructionsBuilder isb = new InstructionsBuilder();
1458 // Instructions List Stores Individual Instructions
1459 List<Instruction> instructions = Lists.newArrayList();
1461 // Call the InstructionBuilder Methods Containing Actions
1462 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1464 ib.setKey(new InstructionKey(0));
1465 instructions.add(ib.build());
1467 // Add InstructionBuilder to the Instruction(s)Builder List
1468 isb.setInstruction(instructions);
1470 // Add InstructionsBuilder to FlowBuilder
1471 flowBuilder.setInstructions(isb.build());
1474 String flowId = "VlanIn_"+segmentationId+"_"+ethPort;
1475 // Add Flow Attributes
1476 flowBuilder.setId(new FlowId(flowId));
1477 FlowKey key = new FlowKey(new FlowId(flowId));
1478 flowBuilder.setStrict(true);
1479 flowBuilder.setBarrier(false);
1480 flowBuilder.setTableId(writeTable);
1481 flowBuilder.setKey(key);
1482 flowBuilder.setFlowName(flowId);
1483 flowBuilder.setHardTimeout(0);
1484 flowBuilder.setIdleTimeout(0);
1486 writeFlow(flowBuilder, nodeBuilder);
1488 removeFlow(flowBuilder, nodeBuilder);
1493 * (Table:0) Egress VM Traffic Towards TEP
1494 * Match: Destination Ethernet Addr and OpenFlow InPort
1495 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1496 * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1497 * actions=set_field:5->tun_id,goto_table=1"
1500 private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
1501 String segmentationId, Long inPort, String attachedMac,
1504 String nodeName = OPENFLOW + dpidLong;
1506 MatchBuilder matchBuilder = new MatchBuilder();
1507 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1508 FlowBuilder flowBuilder = new FlowBuilder();
1510 // Create the OF Match using MatchBuilder
1511 flowBuilder.setMatch(OF13MdSalMatch.createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
1512 // TODO Broken In_Port Match
1513 flowBuilder.setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, inPort).build());
1515 String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
1516 // Add Flow Attributes
1517 flowBuilder.setId(new FlowId(flowId));
1518 FlowKey key = new FlowKey(new FlowId(flowId));
1519 flowBuilder.setStrict(true);
1520 flowBuilder.setBarrier(false);
1521 flowBuilder.setTableId(writeTable);
1522 flowBuilder.setKey(key);
1523 flowBuilder.setFlowName(flowId);
1524 flowBuilder.setHardTimeout(0);
1525 flowBuilder.setIdleTimeout(0);
1528 // Instantiate the Builders for the OF Actions and Instructions
1529 InstructionBuilder ib = new InstructionBuilder();
1530 InstructionsBuilder isb = new InstructionsBuilder();
1532 // Instructions List Stores Individual Instructions
1533 List<Instruction> instructions = Lists.newArrayList();
1535 // GOTO Instructions Need to be added first to the List
1536 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1538 ib.setKey(new InstructionKey(0));
1539 instructions.add(ib.build());
1540 // TODO Broken SetTunID
1541 OF13MdSalInstruction.createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
1543 ib.setKey(new InstructionKey(1));
1544 instructions.add(ib.build());
1546 // Add InstructionBuilder to the Instruction(s)Builder List
1547 isb.setInstruction(instructions);
1549 // Add InstructionsBuilder to FlowBuilder
1550 flowBuilder.setInstructions(isb.build());
1552 writeFlow(flowBuilder, nodeBuilder);
1554 removeFlow(flowBuilder, nodeBuilder);
1559 * (Table:0) Egress VM Traffic Towards TEP
1560 * Match: Source Ethernet Addr and OpenFlow InPort
1561 * Instruction: Set VLANID and GOTO Table Egress (n)
1562 * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1563 * actions=push_vlan, set_field:5->vlan_id,goto_table=1"
1566 private void handleLocalInPortSetVlan(Long dpidLong, Short writeTable,
1567 Short goToTableId, String segmentationId,
1568 Long inPort, String attachedMac,
1571 String nodeName = OPENFLOW + dpidLong;
1573 MatchBuilder matchBuilder = new MatchBuilder();
1574 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1575 FlowBuilder flowBuilder = new FlowBuilder();
1577 // Create the OF Match using MatchBuilder
1578 flowBuilder.setMatch(OF13MdSalMatch.createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
1579 flowBuilder.setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, inPort).build());
1581 String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
1582 // Add Flow Attributes
1583 flowBuilder.setId(new FlowId(flowId));
1584 FlowKey key = new FlowKey(new FlowId(flowId));
1585 flowBuilder.setStrict(true);
1586 flowBuilder.setBarrier(false);
1587 flowBuilder.setTableId(writeTable);
1588 flowBuilder.setKey(key);
1589 flowBuilder.setFlowName(flowId);
1590 flowBuilder.setHardTimeout(0);
1591 flowBuilder.setIdleTimeout(0);
1594 // Instantiate the Builders for the OF Actions and Instructions
1595 InstructionBuilder ib = new InstructionBuilder();
1596 InstructionsBuilder isb = new InstructionsBuilder();
1598 // Instructions List Stores Individual Instructions
1599 List<Instruction> instructions = Lists.newArrayList();
1601 // GOTO Instructions Need to be added first to the List
1602 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1604 ib.setKey(new InstructionKey(0));
1605 instructions.add(ib.build());
1606 // Set VLAN ID Instruction
1607 OF13MdSalInstruction.createSetVlanInstructions(ib, new VlanId(Integer.valueOf(segmentationId)));
1609 ib.setKey(new InstructionKey(1));
1610 instructions.add(ib.build());
1612 // Add InstructionBuilder to the Instruction(s)Builder List
1613 isb.setInstruction(instructions);
1615 // Add InstructionsBuilder to FlowBuilder
1616 flowBuilder.setInstructions(isb.build());
1618 writeFlow(flowBuilder, nodeBuilder);
1620 removeFlow(flowBuilder, nodeBuilder);
1625 * (Table:0) Drop frames source from a VM that do not
1626 * match the associated MAC address of the local VM.
1627 * Match: Low priority anything not matching the VM SMAC
1629 * table=0,priority=16384,in_port=1 actions=drop"
1632 private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
1634 String nodeName = OPENFLOW + dpidLong;
1636 MatchBuilder matchBuilder = new MatchBuilder();
1637 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1638 FlowBuilder flowBuilder = new FlowBuilder();
1640 // Create the OF Match using MatchBuilder
1641 flowBuilder.setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, inPort).build());
1644 // Instantiate the Builders for the OF Actions and Instructions
1645 InstructionBuilder ib = new InstructionBuilder();
1646 InstructionsBuilder isb = new InstructionsBuilder();
1648 // Instructions List Stores Individual Instructions
1649 List<Instruction> instructions = Lists.newArrayList();
1651 // Call the InstructionBuilder Methods Containing Actions
1652 OF13MdSalInstruction.createDropInstructions(ib);
1654 ib.setKey(new InstructionKey(0));
1655 instructions.add(ib.build());
1657 // Add InstructionBuilder to the Instruction(s)Builder List
1658 isb.setInstruction(instructions);
1660 // Add InstructionsBuilder to FlowBuilder
1661 flowBuilder.setInstructions(isb.build());
1664 String flowId = "DropFilter_"+inPort;
1665 // Add Flow Attributes
1666 flowBuilder.setId(new FlowId(flowId));
1667 FlowKey key = new FlowKey(new FlowId(flowId));
1668 flowBuilder.setStrict(true);
1669 flowBuilder.setBarrier(false);
1670 flowBuilder.setTableId(TABLE_0_DEFAULT_INGRESS);
1671 flowBuilder.setKey(key);
1672 flowBuilder.setFlowName(flowId);
1673 flowBuilder.setPriority(8192);
1674 flowBuilder.setHardTimeout(0);
1675 flowBuilder.setIdleTimeout(0);
1677 writeFlow(flowBuilder, nodeBuilder);
1679 removeFlow(flowBuilder, nodeBuilder);
1684 * (Table:1) Egress Tunnel Traffic
1685 * Match: Destination Ethernet Addr and Local InPort
1686 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1687 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
1688 * actions=output:10,goto_table:2"
1690 private void handleTunnelOut(Long dpidLong, Short writeTable,
1691 Short goToTableId, String segmentationId,
1692 Long OFPortOut, String attachedMac,
1695 String nodeName = OPENFLOW + dpidLong;
1697 MatchBuilder matchBuilder = new MatchBuilder();
1698 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1699 FlowBuilder flowBuilder = new FlowBuilder();
1701 // Create the OF Match using MatchBuilder
1702 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1703 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
1705 String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
1706 // Add Flow Attributes
1707 flowBuilder.setId(new FlowId(flowId));
1708 FlowKey key = new FlowKey(new FlowId(flowId));
1709 flowBuilder.setStrict(true);
1710 flowBuilder.setBarrier(false);
1711 flowBuilder.setTableId(writeTable);
1712 flowBuilder.setKey(key);
1713 flowBuilder.setFlowName(flowId);
1714 flowBuilder.setHardTimeout(0);
1715 flowBuilder.setIdleTimeout(0);
1718 // Instantiate the Builders for the OF Actions and Instructions
1719 InstructionBuilder ib = new InstructionBuilder();
1720 InstructionsBuilder isb = new InstructionsBuilder();
1722 // Instructions List Stores Individual Instructions
1723 List<Instruction> instructions = Lists.newArrayList();
1725 // GOTO Instructions
1726 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1728 ib.setKey(new InstructionKey(0));
1729 instructions.add(ib.build());
1730 // Set the Output Port/Iface
1731 OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, OFPortOut);
1733 ib.setKey(new InstructionKey(1));
1734 instructions.add(ib.build());
1736 // Add InstructionBuilder to the Instruction(s)Builder List
1737 isb.setInstruction(instructions);
1739 // Add InstructionsBuilder to FlowBuilder
1740 flowBuilder.setInstructions(isb.build());
1742 writeFlow(flowBuilder, nodeBuilder);
1744 removeFlow(flowBuilder, nodeBuilder);
1749 * (Table:1) Egress VLAN Traffic
1750 * Match: Destination Ethernet Addr and VLAN id
1751 * Instruction: GOTO Table Table 2
1752 * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
1753 * actions= goto_table:2"
1756 private void handleVlanOut(Long dpidLong, Short writeTable,
1757 Short goToTableId, String segmentationId,
1758 Long ethPort, String attachedMac, boolean write) {
1760 String nodeName = OPENFLOW + dpidLong;
1762 MatchBuilder matchBuilder = new MatchBuilder();
1763 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1764 FlowBuilder flowBuilder = new FlowBuilder();
1766 // Create the OF Match using MatchBuilder
1767 flowBuilder.setMatch(
1768 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
1769 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
1771 String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
1772 // Add Flow Attributes
1773 flowBuilder.setId(new FlowId(flowId));
1774 FlowKey key = new FlowKey(new FlowId(flowId));
1775 flowBuilder.setStrict(true);
1776 flowBuilder.setBarrier(false);
1777 flowBuilder.setTableId(writeTable);
1778 flowBuilder.setKey(key);
1779 flowBuilder.setFlowName(flowId);
1780 flowBuilder.setHardTimeout(0);
1781 flowBuilder.setIdleTimeout(0);
1784 // Instantiate the Builders for the OF Actions and Instructions
1785 InstructionBuilder ib = new InstructionBuilder();
1786 InstructionsBuilder isb = new InstructionsBuilder();
1788 // Instructions List Stores Individual Instructions
1789 List<Instruction> instructions = Lists.newArrayList();
1791 // GOTO Instructions
1792 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1794 ib.setKey(new InstructionKey(0));
1795 instructions.add(ib.build());
1797 // Add InstructionBuilder to the Instruction(s)Builder List
1798 isb.setInstruction(instructions);
1800 // Add InstructionsBuilder to FlowBuilder
1801 flowBuilder.setInstructions(isb.build());
1803 writeFlow(flowBuilder, nodeBuilder);
1805 removeFlow(flowBuilder, nodeBuilder);
1810 * (Table:1) Egress Tunnel Traffic
1811 * Match: Destination Ethernet Addr and Local InPort
1812 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1813 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1814 * actions=output:10,output:11,goto_table:2
1817 private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
1818 Short localTable, String segmentationId,
1819 Long OFPortOut, boolean write) {
1821 String nodeName = OPENFLOW + dpidLong;
1823 MatchBuilder matchBuilder = new MatchBuilder();
1824 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1825 FlowBuilder flowBuilder = new FlowBuilder();
1827 // Create the OF Match using MatchBuilder
1829 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1832 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
1833 new MacAddress("01:00:00:00:00:00")).build());
1835 String flowId = "TunnelFloodOut_"+segmentationId;
1836 // Add Flow Attributes
1837 flowBuilder.setId(new FlowId(flowId));
1838 FlowKey key = new FlowKey(new FlowId(flowId));
1839 flowBuilder.setBarrier(true);
1840 flowBuilder.setTableId(writeTable);
1841 flowBuilder.setKey(key);
1842 flowBuilder.setPriority(16384);
1843 flowBuilder.setFlowName(flowId);
1844 flowBuilder.setHardTimeout(0);
1845 flowBuilder.setIdleTimeout(0);
1847 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
1848 // Instantiate the Builders for the OF Actions and Instructions
1849 InstructionBuilder ib = new InstructionBuilder();
1850 InstructionsBuilder isb = new InstructionsBuilder();
1851 List<Instruction> instructions = Lists.newArrayList();
1852 List<Instruction> existingInstructions = null;
1854 Instructions ins = flow.getInstructions();
1856 existingInstructions = ins.getInstruction();
1862 OF13MdSalInstruction.createGotoTableInstructions(ib, localTable);
1864 ib.setKey(new InstructionKey(0));
1865 instructions.add(ib.build());
1866 // Set the Output Port/Iface
1867 //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
1868 createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
1870 ib.setKey(new InstructionKey(1));
1871 instructions.add(ib.build());
1873 // Add InstructionBuilder to the Instruction(s)Builder List
1874 isb.setInstruction(instructions);
1876 // Add InstructionsBuilder to FlowBuilder
1877 flowBuilder.setInstructions(isb.build());
1879 writeFlow(flowBuilder, nodeBuilder);
1881 /* remove port from action list */
1882 boolean flowRemove = OF13MdSalInstruction.removeOutputPortFromInstructions(ib, dpidLong,
1883 OFPortOut, existingInstructions);
1885 /* if all port are removed, remove the flow too. */
1886 removeFlow(flowBuilder, nodeBuilder);
1888 /* Install instruction with new output port list*/
1890 ib.setKey(new InstructionKey(0));
1891 instructions.add(ib.build());
1893 // Add InstructionBuilder to the Instruction(s)Builder List
1894 isb.setInstruction(instructions);
1896 // Add InstructionsBuilder to FlowBuilder
1897 flowBuilder.setInstructions(isb.build());
1903 * (Table:1) Egress VLAN Traffic
1904 * Match: Destination Ethernet Addr and VLAN id
1905 * Instruction: GOTO table 2 and Output port eth interface
1906 * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1907 * actions=output:eth1,goto_table:2
1910 private void handleVlanFloodOut(Long dpidLong, Short writeTable,
1911 Short localTable, String segmentationId,
1912 Long ethPort, boolean write) {
1914 String nodeName = OPENFLOW + dpidLong;
1916 MatchBuilder matchBuilder = new MatchBuilder();
1917 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1918 FlowBuilder flowBuilder = new FlowBuilder();
1920 // Create the OF Match using MatchBuilder
1922 flowBuilder.setMatch(
1923 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
1925 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
1926 new MacAddress("01:00:00:00:00:00")).build());
1928 String flowId = "VlanFloodOut_"+segmentationId;
1929 // Add Flow Attributes
1930 flowBuilder.setId(new FlowId(flowId));
1931 FlowKey key = new FlowKey(new FlowId(flowId));
1932 flowBuilder.setBarrier(true);
1933 flowBuilder.setTableId(writeTable);
1934 flowBuilder.setKey(key);
1935 flowBuilder.setPriority(16384);
1936 flowBuilder.setFlowName(flowId);
1937 flowBuilder.setHardTimeout(0);
1938 flowBuilder.setIdleTimeout(0);
1940 //ToDo: Is there something to be done with result of the call to getFlow?
1942 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
1943 // Instantiate the Builders for the OF Actions and Instructions
1944 InstructionBuilder ib = new InstructionBuilder();
1945 InstructionsBuilder isb = new InstructionsBuilder();
1946 List<Instruction> instructions = Lists.newArrayList();
1950 OF13MdSalInstruction.createGotoTableInstructions(ib, localTable);
1952 ib.setKey(new InstructionKey(0));
1953 instructions.add(ib.build());
1954 // Set the Output Port/Iface
1955 OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, ethPort);
1957 ib.setKey(new InstructionKey(1));
1958 instructions.add(ib.build());
1960 // Add InstructionBuilder to the Instruction(s)Builder List
1961 isb.setInstruction(instructions);
1963 // Add InstructionsBuilder to FlowBuilder
1964 flowBuilder.setInstructions(isb.build());
1966 writeFlow(flowBuilder, nodeBuilder);
1968 removeFlow(flowBuilder, nodeBuilder);
1973 * (Table:1) Table Drain w/ Catch All
1975 * Action: GOTO Local Table (10)
1976 * table=2,priority=8192,tun_id=0x5 actions=drop
1979 private void handleTunnelMiss(Long dpidLong, Short writeTable,
1980 Short goToTableId, String segmentationId,
1983 String nodeName = OPENFLOW + dpidLong;
1985 MatchBuilder matchBuilder = new MatchBuilder();
1986 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1987 FlowBuilder flowBuilder = new FlowBuilder();
1989 // Create Match(es) and Set them in the FlowBuilder Object
1990 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1993 // Create the OF Actions and Instructions
1994 InstructionBuilder ib = new InstructionBuilder();
1995 InstructionsBuilder isb = new InstructionsBuilder();
1997 // Instructions List Stores Individual Instructions
1998 List<Instruction> instructions = Lists.newArrayList();
2000 // Call the InstructionBuilder Methods Containing Actions
2001 OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
2003 ib.setKey(new InstructionKey(0));
2004 instructions.add(ib.build());
2006 // Add InstructionBuilder to the Instruction(s)Builder List
2007 isb.setInstruction(instructions);
2009 // Add InstructionsBuilder to FlowBuilder
2010 flowBuilder.setInstructions(isb.build());
2013 String flowId = "TunnelMiss_"+segmentationId;
2014 // Add Flow Attributes
2015 flowBuilder.setId(new FlowId(flowId));
2016 FlowKey key = new FlowKey(new FlowId(flowId));
2017 flowBuilder.setStrict(true);
2018 flowBuilder.setBarrier(false);
2019 flowBuilder.setTableId(writeTable);
2020 flowBuilder.setKey(key);
2021 flowBuilder.setPriority(8192);
2022 flowBuilder.setFlowName(flowId);
2023 flowBuilder.setHardTimeout(0);
2024 flowBuilder.setIdleTimeout(0);
2026 writeFlow(flowBuilder, nodeBuilder);
2028 removeFlow(flowBuilder, nodeBuilder);
2034 * (Table:1) Table Drain w/ Catch All
2036 * Action: Output port eth interface
2037 * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
2040 private void handleVlanMiss(Long dpidLong, Short writeTable,
2041 Short goToTableId, String segmentationId,
2042 Long ethPort, boolean write) {
2044 String nodeName = OPENFLOW + dpidLong;
2046 MatchBuilder matchBuilder = new MatchBuilder();
2047 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2048 FlowBuilder flowBuilder = new FlowBuilder();
2050 // Create Match(es) and Set them in the FlowBuilder Object
2051 flowBuilder.setMatch(
2052 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2055 // Create the OF Actions and Instructions
2056 InstructionBuilder ib = new InstructionBuilder();
2057 InstructionsBuilder isb = new InstructionsBuilder();
2059 // Instructions List Stores Individual Instructions
2060 List<Instruction> instructions = Lists.newArrayList();
2062 // Call the InstructionBuilder Methods Containing Actions
2063 //createGotoTableInstructions(ib, goToTableId);
2065 //ib.setKey(new InstructionKey(0));
2066 //instructions.add(ib.build());
2067 // Set the Output Port/Iface
2068 OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, ethPort);
2070 ib.setKey(new InstructionKey(1));
2071 instructions.add(ib.build());
2073 // Add InstructionBuilder to the Instruction(s)Builder List
2074 isb.setInstruction(instructions);
2076 // Add InstructionsBuilder to FlowBuilder
2077 flowBuilder.setInstructions(isb.build());
2080 String flowId = "VlanMiss_"+segmentationId;
2081 // Add Flow Attributes
2082 flowBuilder.setId(new FlowId(flowId));
2083 FlowKey key = new FlowKey(new FlowId(flowId));
2084 flowBuilder.setStrict(true);
2085 flowBuilder.setBarrier(false);
2086 flowBuilder.setTableId(writeTable);
2087 flowBuilder.setKey(key);
2088 flowBuilder.setPriority(8192);
2089 flowBuilder.setFlowName(flowId);
2090 flowBuilder.setHardTimeout(0);
2091 flowBuilder.setIdleTimeout(0);
2093 writeFlow(flowBuilder, nodeBuilder);
2095 removeFlow(flowBuilder, nodeBuilder);
2100 * (Table:1) Local Broadcast Flood
2101 * Match: Tunnel ID and dMAC
2102 * Action: Output Port
2103 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
2106 private void handleLocalUcastOut(Long dpidLong, Short writeTable,
2107 String segmentationId, Long localPort,
2108 String attachedMac, boolean write) {
2110 String nodeName = OPENFLOW + dpidLong;
2112 MatchBuilder matchBuilder = new MatchBuilder();
2113 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2114 FlowBuilder flowBuilder = new FlowBuilder();
2116 // Create the OF Match using MatchBuilder
2117 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2118 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
2120 String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
2121 // Add Flow Attributes
2122 flowBuilder.setId(new FlowId(flowId));
2123 FlowKey key = new FlowKey(new FlowId(flowId));
2124 flowBuilder.setStrict(true);
2125 flowBuilder.setBarrier(false);
2126 flowBuilder.setTableId(writeTable);
2127 flowBuilder.setKey(key);
2128 flowBuilder.setFlowName(flowId);
2129 flowBuilder.setHardTimeout(0);
2130 flowBuilder.setIdleTimeout(0);
2133 // Instantiate the Builders for the OF Actions and Instructions
2134 InstructionBuilder ib = new InstructionBuilder();
2135 InstructionsBuilder isb = new InstructionsBuilder();
2137 // Instructions List Stores Individual Instructions
2138 List<Instruction> instructions = Lists.newArrayList();
2140 // Set the Output Port/Iface
2141 OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, localPort);
2143 ib.setKey(new InstructionKey(0));
2144 instructions.add(ib.build());
2146 // Add InstructionBuilder to the Instruction(s)Builder List
2147 isb.setInstruction(instructions);
2149 // Add InstructionsBuilder to FlowBuilder
2150 flowBuilder.setInstructions(isb.build());
2151 writeFlow(flowBuilder, nodeBuilder);
2153 removeFlow(flowBuilder, nodeBuilder);
2158 * (Table:2) Local VLAN unicast
2159 * Match: VLAN ID and dMAC
2160 * Action: Output Port
2161 * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
2164 private void handleLocalVlanUcastOut(Long dpidLong, Short writeTable,
2165 String segmentationId, Long localPort,
2166 String attachedMac, boolean write) {
2168 String nodeName = OPENFLOW + dpidLong;
2170 MatchBuilder matchBuilder = new MatchBuilder();
2171 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2172 FlowBuilder flowBuilder = new FlowBuilder();
2174 // Create the OF Match using MatchBuilder
2175 flowBuilder.setMatch(
2176 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2177 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
2179 String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
2180 // Add Flow Attributes
2181 flowBuilder.setId(new FlowId(flowId));
2182 FlowKey key = new FlowKey(new FlowId(flowId));
2183 flowBuilder.setStrict(true);
2184 flowBuilder.setBarrier(false);
2185 flowBuilder.setTableId(writeTable);
2186 flowBuilder.setKey(key);
2187 flowBuilder.setFlowName(flowId);
2188 flowBuilder.setHardTimeout(0);
2189 flowBuilder.setIdleTimeout(0);
2192 // Instantiate the Builders for the OF Actions and Instructions
2193 InstructionBuilder ib = new InstructionBuilder();
2194 InstructionsBuilder isb = new InstructionsBuilder();
2196 // Instructions List Stores Individual Instructions
2197 List<Instruction> instructions = Lists.newArrayList();
2198 List<Instruction> instructions_tmp = Lists.newArrayList();
2200 /* Strip vlan and store to tmp instruction space*/
2201 OF13MdSalInstruction.createPopVlanInstructions(ib);
2203 ib.setKey(new InstructionKey(0));
2204 instructions_tmp.add(ib.build());
2206 // Set the Output Port/Iface
2207 ib = new InstructionBuilder();
2208 OF13MdSalInstruction.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
2210 ib.setKey(new InstructionKey(0));
2211 instructions.add(ib.build());
2213 // Add InstructionBuilder to the Instruction(s)Builder List
2214 isb.setInstruction(instructions);
2216 // Add InstructionsBuilder to FlowBuilder
2217 flowBuilder.setInstructions(isb.build());
2218 writeFlow(flowBuilder, nodeBuilder);
2220 removeFlow(flowBuilder, nodeBuilder);
2225 * (Table:2) Local Broadcast Flood
2226 * Match: Tunnel ID and dMAC (::::FF:FF)
2227 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
2228 * actions=output:2,3,4,5
2231 private void handleLocalBcastOut(Long dpidLong, Short writeTable,
2232 String segmentationId, Long localPort,
2235 String nodeName = OPENFLOW + dpidLong;
2237 MatchBuilder matchBuilder = new MatchBuilder();
2238 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2239 FlowBuilder flowBuilder = new FlowBuilder();
2241 // Create the OF Match using MatchBuilder
2242 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2243 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
2244 new MacAddress("01:00:00:00:00:00")).build());
2246 String flowId = "BcastOut_"+segmentationId;
2247 // Add Flow Attributes
2248 flowBuilder.setId(new FlowId(flowId));
2249 FlowKey key = new FlowKey(new FlowId(flowId));
2250 flowBuilder.setStrict(true);
2251 flowBuilder.setBarrier(false);
2252 flowBuilder.setTableId(writeTable);
2253 flowBuilder.setKey(key);
2254 flowBuilder.setPriority(16384);
2255 flowBuilder.setFlowName(flowId);
2256 flowBuilder.setHardTimeout(0);
2257 flowBuilder.setIdleTimeout(0);
2258 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
2259 // Instantiate the Builders for the OF Actions and Instructions
2260 InstructionBuilder ib = new InstructionBuilder();
2261 InstructionsBuilder isb = new InstructionsBuilder();
2262 List<Instruction> instructions = Lists.newArrayList();
2263 List<Instruction> existingInstructions = null;
2265 Instructions ins = flow.getInstructions();
2267 existingInstructions = ins.getInstruction();
2272 // Create output port list
2273 createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
2275 ib.setKey(new InstructionKey(0));
2276 instructions.add(ib.build());
2278 // Add InstructionBuilder to the Instruction(s)Builder List
2279 isb.setInstruction(instructions);
2281 // Add InstructionsBuilder to FlowBuilder
2282 flowBuilder.setInstructions(isb.build());
2284 writeFlow(flowBuilder, nodeBuilder);
2286 boolean flowRemove = OF13MdSalInstruction.removeOutputPortFromInstructions(ib, dpidLong, localPort,
2287 existingInstructions);
2289 /* if all ports are removed, remove flow */
2290 removeFlow(flowBuilder, nodeBuilder);
2292 /* Install instruction with new output port list*/
2294 ib.setKey(new InstructionKey(0));
2295 instructions.add(ib.build());
2297 // Add InstructionBuilder to the Instruction(s)Builder List
2298 isb.setInstruction(instructions);
2300 // Add InstructionsBuilder to FlowBuilder
2301 flowBuilder.setInstructions(isb.build());
2303 writeFlow(flowBuilder, nodeBuilder);
2309 * (Table:2) Local VLAN Broadcast Flood
2310 * Match: vlan ID and dMAC (::::FF:FF)
2311 * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
2312 * actions=strip_vlan, output:2,3,4,5
2315 private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable,
2316 String segmentationId, Long localPort,
2319 String nodeName = OPENFLOW + dpidLong;
2321 MatchBuilder matchBuilder = new MatchBuilder();
2322 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2323 FlowBuilder flowBuilder = new FlowBuilder();
2325 // Create the OF Match using MatchBuilder
2326 flowBuilder.setMatch(
2327 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2328 flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
2329 new MacAddress("01:00:00:00:00:00")).build());
2331 String flowId = "VlanBcastOut_"+segmentationId;
2332 // Add Flow Attributes
2333 flowBuilder.setId(new FlowId(flowId));
2334 FlowKey key = new FlowKey(new FlowId(flowId));
2335 flowBuilder.setStrict(true);
2336 flowBuilder.setBarrier(false);
2337 flowBuilder.setTableId(writeTable);
2338 flowBuilder.setKey(key);
2339 flowBuilder.setPriority(16384);
2340 flowBuilder.setFlowName(flowId);
2341 flowBuilder.setHardTimeout(0);
2342 flowBuilder.setIdleTimeout(0);
2343 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
2344 // Instantiate the Builders for the OF Actions and Instructions
2345 InstructionBuilder ib = new InstructionBuilder();
2346 InstructionsBuilder isb = new InstructionsBuilder();
2347 List<Instruction> instructions = Lists.newArrayList();
2348 List<Instruction> existingInstructions = null;
2349 boolean add_pop_vlan = true;
2351 Instructions ins = flow.getInstructions();
2353 existingInstructions = ins.getInstruction();
2358 if (existingInstructions != null) {
2359 /* Check if pop vlan is already the first action in action list */
2360 List<Action> existingActions;
2361 for (Instruction in : existingInstructions) {
2362 if (in.getInstruction() instanceof ApplyActionsCase) {
2363 existingActions = (((ApplyActionsCase)
2364 in.getInstruction()).getApplyActions().getAction());
2365 if (existingActions.get(0).getAction() instanceof PopVlanActionCase) {
2366 add_pop_vlan = false;
2372 existingInstructions = Lists.newArrayList();
2377 OF13MdSalInstruction.createPopVlanInstructions(ib);
2379 ib.setKey(new InstructionKey(0));
2380 existingInstructions.add(ib.build());
2381 ib = new InstructionBuilder();
2385 //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, localPort, existingInstructions);
2386 createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
2388 ib.setKey(new InstructionKey(0));
2389 instructions.add(ib.build());
2391 // Add InstructionBuilder to the Instruction(s)Builder List
2392 isb.setInstruction(instructions);
2394 // Add InstructionsBuilder to FlowBuilder
2395 flowBuilder.setInstructions(isb.build());
2397 writeFlow(flowBuilder, nodeBuilder);
2399 //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
2400 // localPort, existingInstructions);
2401 boolean flowRemove = OF13MdSalInstruction.removeOutputPortFromInstructions(ib, dpidLong,
2402 localPort, existingInstructions);
2404 /* if all ports are removed, remove flow */
2405 removeFlow(flowBuilder, nodeBuilder);
2407 /* Install instruction with new output port list*/
2409 ib.setKey(new InstructionKey(0));
2410 instructions.add(ib.build());
2412 // Add InstructionBuilder to the Instruction(s)Builder List
2413 isb.setInstruction(instructions);
2415 // Add InstructionsBuilder to FlowBuilder
2416 flowBuilder.setInstructions(isb.build());
2417 writeFlow(flowBuilder, nodeBuilder);
2423 * (Table:1) Local Table Miss
2424 * Match: Any Remaining Flows w/a TunID
2425 * Action: Drop w/ a low priority
2426 * table=2,priority=8192,tun_id=0x5 actions=drop
2429 private void handleLocalTableMiss(Long dpidLong, Short writeTable,
2430 String segmentationId, boolean write) {
2432 String nodeName = OPENFLOW + dpidLong;
2434 MatchBuilder matchBuilder = new MatchBuilder();
2435 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2436 FlowBuilder flowBuilder = new FlowBuilder();
2438 // Create Match(es) and Set them in the FlowBuilder Object
2439 flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2442 // Create the OF Actions and Instructions
2443 InstructionBuilder ib = new InstructionBuilder();
2444 InstructionsBuilder isb = new InstructionsBuilder();
2446 // Instructions List Stores Individual Instructions
2447 List<Instruction> instructions = Lists.newArrayList();
2449 // Call the InstructionBuilder Methods Containing Actions
2450 OF13MdSalInstruction.createDropInstructions(ib);
2452 ib.setKey(new InstructionKey(0));
2453 instructions.add(ib.build());
2455 // Add InstructionBuilder to the Instruction(s)Builder List
2456 isb.setInstruction(instructions);
2458 // Add InstructionsBuilder to FlowBuilder
2459 flowBuilder.setInstructions(isb.build());
2462 String flowId = "LocalTableMiss_"+segmentationId;
2463 // Add Flow Attributes
2464 flowBuilder.setId(new FlowId(flowId));
2465 FlowKey key = new FlowKey(new FlowId(flowId));
2466 flowBuilder.setStrict(true);
2467 flowBuilder.setBarrier(false);
2468 flowBuilder.setTableId(writeTable);
2469 flowBuilder.setKey(key);
2470 flowBuilder.setPriority(8192);
2471 flowBuilder.setFlowName(flowId);
2472 flowBuilder.setHardTimeout(0);
2473 flowBuilder.setIdleTimeout(0);
2475 writeFlow(flowBuilder, nodeBuilder);
2477 removeFlow(flowBuilder, nodeBuilder);
2482 * (Table:1) Local Table Miss
2483 * Match: Any Remaining Flows w/a VLAN ID
2484 * Action: Drop w/ a low priority
2485 * table=2,priority=8192,vlan_id=0x5 actions=drop
2488 private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
2489 String segmentationId, boolean write) {
2491 String nodeName = OPENFLOW + dpidLong;
2493 MatchBuilder matchBuilder = new MatchBuilder();
2494 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2495 FlowBuilder flowBuilder = new FlowBuilder();
2497 // Create Match(es) and Set them in the FlowBuilder Object
2498 flowBuilder.setMatch(
2499 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2502 // Create the OF Actions and Instructions
2503 InstructionBuilder ib = new InstructionBuilder();
2504 InstructionsBuilder isb = new InstructionsBuilder();
2506 // Instructions List Stores Individual Instructions
2507 List<Instruction> instructions = Lists.newArrayList();
2509 // Call the InstructionBuilder Methods Containing Actions
2510 OF13MdSalInstruction.createDropInstructions(ib);
2512 ib.setKey(new InstructionKey(0));
2513 instructions.add(ib.build());
2515 // Add InstructionBuilder to the Instruction(s)Builder List
2516 isb.setInstruction(instructions);
2518 // Add InstructionsBuilder to FlowBuilder
2519 flowBuilder.setInstructions(isb.build());
2522 String flowId = "LocalTableMiss_"+segmentationId;
2523 // Add Flow Attributes
2524 flowBuilder.setId(new FlowId(flowId));
2525 FlowKey key = new FlowKey(new FlowId(flowId));
2526 flowBuilder.setStrict(true);
2527 flowBuilder.setBarrier(false);
2528 flowBuilder.setTableId(writeTable);
2529 flowBuilder.setKey(key);
2530 flowBuilder.setPriority(8192);
2531 flowBuilder.setFlowName(flowId);
2532 flowBuilder.setHardTimeout(0);
2533 flowBuilder.setIdleTimeout(0);
2535 writeFlow(flowBuilder, nodeBuilder);
2537 removeFlow(flowBuilder, nodeBuilder);
2541 private Group getGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
2542 Preconditions.checkNotNull(mdsalConsumer);
2543 if (mdsalConsumer == null) {
2544 logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2548 dataBroker = mdsalConsumer.getDataBroker();
2549 if (dataBroker == null) {
2550 logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2554 InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2555 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
2556 new GroupKey(groupBuilder.getGroupId())).build();
2557 ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
2559 Optional<Group> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
2560 if (data.isPresent()) {
2563 } catch (InterruptedException|ExecutionException e) {
2564 logger.error(e.getMessage(), e);
2567 logger.debug("Cannot find data for Group " + groupBuilder.getGroupName());
2571 private void writeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
2572 Preconditions.checkNotNull(mdsalConsumer);
2573 if (mdsalConsumer == null) {
2574 logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2578 dataBroker = mdsalConsumer.getDataBroker();
2579 if (dataBroker == null) {
2580 logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2584 ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
2586 // Sanity check: do not create parent's tree deeper than we should
2587 InstanceIdentifier<?> requiredPath = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2588 .rev130819.nodes.Node.class, nodeBuilder.getKey()).build();
2590 if (!modification.read(LogicalDatastoreType.CONFIGURATION, requiredPath).get().isPresent()) {
2591 logger.error("Unable to get configuration resource to store group "+groupBuilder.getGroupName()
2592 +" ("+requiredPath.toString()+")");
2595 } catch (InterruptedException|ExecutionException e) {
2596 logger.error(e.getMessage(), e);
2600 InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2601 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
2602 new GroupKey(groupBuilder.getGroupId())).build();
2603 modification.put(LogicalDatastoreType.CONFIGURATION, path1, groupBuilder.build(), true /*createMissingParents*/);
2605 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2607 commitFuture.get(); // TODO: Make it async (See bug 1362)
2608 logger.debug("Transaction success for write of Group "+groupBuilder.getGroupName());
2609 } catch (InterruptedException|ExecutionException e) {
2610 logger.error(e.getMessage(), e);
2614 private void removeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
2615 Preconditions.checkNotNull(mdsalConsumer);
2616 if (mdsalConsumer == null) {
2617 logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2621 dataBroker = mdsalConsumer.getDataBroker();
2622 if (dataBroker == null) {
2623 logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2627 WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
2628 InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2629 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
2630 new GroupKey(groupBuilder.getGroupId())).build();
2631 modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
2632 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2635 commitFuture.get(); // TODO: Make it async (See bug 1362)
2636 logger.debug("Transaction success for deletion of Group "+groupBuilder.getGroupName());
2637 } catch (InterruptedException|ExecutionException e) {
2638 logger.error(e.getMessage(), e);
2641 private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2642 Preconditions.checkNotNull(mdsalConsumer);
2643 if (mdsalConsumer == null) {
2644 logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2648 dataBroker = mdsalConsumer.getDataBroker();
2649 if (dataBroker == null) {
2650 logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2654 InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2655 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
2656 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
2658 ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
2660 Optional<Flow> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
2661 if (data.isPresent()) {
2664 } catch (InterruptedException|ExecutionException e) {
2665 logger.error(e.getMessage(), e);
2668 logger.debug("Cannot find data for Flow " + flowBuilder.getFlowName());
2672 private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2673 Preconditions.checkNotNull(mdsalConsumer);
2674 if (mdsalConsumer == null) {
2675 logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2679 dataBroker = mdsalConsumer.getDataBroker();
2680 if (dataBroker == null) {
2681 logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2685 ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
2687 // Sanity check: do not create parent's tree deeper than we should
2688 InstanceIdentifier<?> requiredPath = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2689 .rev130819.nodes.Node.class, nodeBuilder.getKey()).build();
2691 if (!modification.read(LogicalDatastoreType.CONFIGURATION, requiredPath).get().isPresent()) {
2692 logger.error("Unable to get configuration resource to store flow "+flowBuilder.getFlowName()
2693 +" ("+requiredPath.toString()+")");
2696 } catch (InterruptedException|ExecutionException e) {
2697 logger.error(e.getMessage(), e);
2701 InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2702 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
2703 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
2705 //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
2706 modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(), true /*createMissingParents*/);
2709 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2711 commitFuture.get(); // TODO: Make it async (See bug 1362)
2712 logger.debug("Transaction success for write of Flow "+flowBuilder.getFlowName());
2713 } catch (InterruptedException|ExecutionException e) {
2714 logger.error(e.getMessage(), e);
2718 private void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2719 Preconditions.checkNotNull(mdsalConsumer);
2720 if (mdsalConsumer == null) {
2721 logger.error("ERROR finding MDSAL Service.");
2725 dataBroker = mdsalConsumer.getDataBroker();
2726 if (dataBroker == null) {
2727 logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2731 WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
2732 InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
2733 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2734 .rev130819.nodes.Node.class, nodeBuilder.getKey())
2735 .augmentation(FlowCapableNode.class).child(Table.class,
2736 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
2737 //modification.delete(LogicalDatastoreType.OPERATIONAL, nodeBuilderToInstanceId(nodeBuilder));
2738 //modification.delete(LogicalDatastoreType.OPERATIONAL, path1);
2739 //modification.delete(LogicalDatastoreType.CONFIGURATION, nodeBuilderToInstanceId(nodeBuilder));
2740 modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
2742 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2744 commitFuture.get(); // TODO: Make it async (See bug 1362)
2745 logger.debug("Transaction success for deletion of Flow "+flowBuilder.getFlowName());
2746 } catch (InterruptedException|ExecutionException e) {
2747 logger.error(e.getMessage(), e);
2752 * Create Output Port Group Instruction
2754 * @param ib Map InstructionBuilder without any instructions
2755 * @param dpidLong Long the datapath ID of a switch/node
2756 * @param port Long representing a port on a switch/node
2757 * @return ib InstructionBuilder Map with instructions
2759 protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
2760 Long dpidLong, Long port ,
2761 List<Instruction> instructions) {
2762 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
2763 logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
2765 List<Action> actionList = Lists.newArrayList();
2766 ActionBuilder ab = new ActionBuilder();
2768 List<Action> existingActions;
2769 if (instructions != null) {
2770 for (Instruction in : instructions) {
2771 if (in.getInstruction() instanceof ApplyActionsCase) {
2772 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
2773 actionList.addAll(existingActions);
2777 /* Create output action for this port*/
2778 OutputActionBuilder oab = new OutputActionBuilder();
2779 oab.setOutputNodeConnector(ncid);
2780 ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
2781 boolean addNew = true;
2783 /* Find the group action and get the group */
2784 for (Action action : actionList) {
2785 if (action.getAction() instanceof OutputActionCase) {
2786 OutputActionCase opAction = (OutputActionCase)action.getAction();
2787 /* If output port action already in the action list of one of the buckets, skip */
2788 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
2795 ab.setOrder(actionList.size());
2796 ab.setKey(new ActionKey(actionList.size()));
2797 actionList.add(ab.build());
2799 // Create an Apply Action
2800 ApplyActionsBuilder aab = new ApplyActionsBuilder();
2801 aab.setAction(actionList);
2802 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2803 logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());
2808 * Create Output Port Group Instruction
2810 * @param ib Map InstructionBuilder without any instructions
2811 * @param dpidLong Long the datapath ID of a switch/node
2812 * @param port Long representing a port on a switch/node
2813 * @return ib InstructionBuilder Map with instructions
2815 protected InstructionBuilder createOutputGroupInstructions(NodeBuilder nodeBuilder,
2816 InstructionBuilder ib,
2817 Long dpidLong, Long port ,
2818 List<Instruction> instructions) {
2819 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
2820 logger.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
2822 List<Action> actionList = Lists.newArrayList();
2823 ActionBuilder ab = new ActionBuilder();
2825 List<Action> existingActions;
2826 if (instructions != null) {
2827 for (Instruction in : instructions) {
2828 if (in.getInstruction() instanceof ApplyActionsCase) {
2829 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
2830 actionList.addAll(existingActions);
2835 GroupBuilder groupBuilder = new GroupBuilder();
2838 /* Create output action for this port*/
2839 OutputActionBuilder oab = new OutputActionBuilder();
2840 oab.setOutputNodeConnector(ncid);
2841 ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
2842 logger.debug("createOutputGroupInstructions(): output action {}", ab.build());
2843 boolean addNew = true;
2844 boolean groupActionAdded = false;
2846 /* Find the group action and get the group */
2847 for (Action action : actionList) {
2848 if (action.getAction() instanceof GroupActionCase) {
2849 groupActionAdded = true;
2850 GroupActionCase groupAction = (GroupActionCase) action.getAction();
2851 Long id = groupAction.getGroupAction().getGroupId();
2852 String groupName = groupAction.getGroupAction().getGroup();
2853 GroupKey key = new GroupKey(new GroupId(id));
2855 groupBuilder.setGroupId(new GroupId(id));
2856 groupBuilder.setGroupName(groupName);
2857 groupBuilder.setGroupType(GroupTypes.GroupAll);
2858 groupBuilder.setKey(key);
2859 group = getGroup(groupBuilder, nodeBuilder);
2860 logger.debug("createOutputGroupInstructions: group {}", group);
2865 logger.debug("createOutputGroupInstructions: groupActionAdded {}", groupActionAdded);
2866 if (groupActionAdded) {
2867 /* modify the action bucket in group */
2868 groupBuilder = new GroupBuilder(group);
2869 Buckets buckets = groupBuilder.getBuckets();
2870 for (Bucket bucket : buckets.getBucket()) {
2871 List<Action> bucketActions = bucket.getAction();
2872 logger.debug("createOutputGroupInstructions: bucketActions {}", bucketActions);
2873 for (Action action : bucketActions) {
2874 if (action.getAction() instanceof OutputActionCase) {
2875 OutputActionCase opAction = (OutputActionCase)action.getAction();
2876 /* If output port action already in the action list of one of the buckets, skip */
2877 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
2884 logger.debug("createOutputGroupInstructions: addNew {}", addNew);
2886 /* the new output action is not in the bucket, add to bucket */
2887 if (!buckets.getBucket().isEmpty()) {
2888 Bucket bucket = buckets.getBucket().get(0);
2889 List<Action> bucketActionList = Lists.newArrayList();
2890 bucketActionList.addAll(bucket.getAction());
2891 /* set order for new action and add to action list */
2892 ab.setOrder(bucketActionList.size());
2893 ab.setKey(new ActionKey(bucketActionList.size()));
2894 bucketActionList.add(ab.build());
2896 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
2897 BucketsBuilder bucketsBuilder = new BucketsBuilder();
2898 List<Bucket> bucketList = Lists.newArrayList();
2899 BucketBuilder bucketBuilder = new BucketBuilder();
2900 bucketBuilder.setBucketId(new BucketId((long) 1));
2901 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
2902 bucketBuilder.setAction(bucketActionList);
2903 bucketList.add(bucketBuilder.build());
2904 bucketsBuilder.setBucket(bucketList);
2905 groupBuilder.setBuckets(bucketsBuilder.build());
2906 logger.debug("createOutputGroupInstructions: bucketList {}", bucketList);
2911 groupBuilder = new GroupBuilder();
2912 groupBuilder.setGroupType(GroupTypes.GroupAll);
2913 groupBuilder.setGroupId(new GroupId(groupId));
2914 groupBuilder.setKey(new GroupKey(new GroupId(groupId)));
2915 groupBuilder.setGroupName("Output port group " + groupId);
2916 groupBuilder.setBarrier(false);
2918 BucketsBuilder bucketBuilder = new BucketsBuilder();
2919 List<Bucket> bucketList = Lists.newArrayList();
2920 BucketBuilder bucket = new BucketBuilder();
2921 bucket.setBucketId(new BucketId((long) 1));
2922 bucket.setKey(new BucketKey(new BucketId((long) 1)));
2924 /* put output action to the bucket */
2925 List<Action> bucketActionList = Lists.newArrayList();
2926 /* set order for new action and add to action list */
2927 ab.setOrder(bucketActionList.size());
2928 ab.setKey(new ActionKey(bucketActionList.size()));
2929 bucketActionList.add(ab.build());
2931 bucket.setAction(bucketActionList);
2932 bucketList.add(bucket.build());
2933 bucketBuilder.setBucket(bucketList);
2934 groupBuilder.setBuckets(bucketBuilder.build());
2936 /* Add new group action */
2937 GroupActionBuilder groupActionB = new GroupActionBuilder();
2938 groupActionB.setGroupId(groupId);
2939 groupActionB.setGroup("Output port group " + groupId);
2940 ab = new ActionBuilder();
2941 ab.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionB.build()).build());
2942 ab.setOrder(actionList.size());
2943 ab.setKey(new ActionKey(actionList.size()));
2944 actionList.add(ab.build());
2948 logger.debug("createOutputGroupInstructions: group {}", groupBuilder.build());
2949 logger.debug("createOutputGroupInstructions: actionList {}", actionList);
2952 /* rewrite the group to group table */
2953 writeGroup(groupBuilder, nodeBuilder);
2956 // Create an Apply Action
2957 ApplyActionsBuilder aab = new ApplyActionsBuilder();
2958 aab.setAction(actionList);
2959 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2965 * Remove Output Port from action list in group bucket
2967 * @param ib Map InstructionBuilder without any instructions
2968 * @param dpidLong Long the datapath ID of a switch/node
2969 * @param port Long representing a port on a switch/node
2970 * @return ib InstructionBuilder Map with instructions
2972 protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
2973 Long dpidLong, Long port , List<Instruction> instructions) {
2975 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
2976 logger.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
2978 List<Action> actionList = Lists.newArrayList();
2981 List<Action> existingActions;
2982 if (instructions != null) {
2983 for (Instruction in : instructions) {
2984 if (in.getInstruction() instanceof ApplyActionsCase) {
2985 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
2986 actionList.addAll(existingActions);
2992 GroupBuilder groupBuilder = new GroupBuilder();
2994 boolean groupActionAdded = false;
2995 /* Find the group action and get the group */
2996 for (Action action : actionList) {
2997 if (action.getAction() instanceof GroupActionCase) {
2998 groupActionAdded = true;
2999 GroupActionCase groupAction = (GroupActionCase) action.getAction();
3000 Long id = groupAction.getGroupAction().getGroupId();
3001 String groupName = groupAction.getGroupAction().getGroup();
3002 GroupKey key = new GroupKey(new GroupId(id));
3004 groupBuilder.setGroupId(new GroupId(id));
3005 groupBuilder.setGroupName(groupName);
3006 groupBuilder.setGroupType(GroupTypes.GroupAll);
3007 groupBuilder.setKey(key);
3008 group = getGroup(groupBuilder, nodeBuilder);
3013 if (groupActionAdded) {
3014 /* modify the action bucket in group */
3015 groupBuilder = new GroupBuilder(group);
3016 Buckets buckets = groupBuilder.getBuckets();
3017 List<Action> bucketActions = Lists.newArrayList();
3018 for (Bucket bucket : buckets.getBucket()) {
3020 boolean isPortDeleted = false;
3021 bucketActions = bucket.getAction();
3022 for (Action action : bucketActions) {
3023 if (action.getAction() instanceof OutputActionCase) {
3024 OutputActionCase opAction = (OutputActionCase)action.getAction();
3025 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
3026 /* Find the output port in action list and remove */
3027 index = bucketActions.indexOf(action);
3028 bucketActions.remove(action);
3029 isPortDeleted = true;
3034 if (isPortDeleted && !bucketActions.isEmpty()) {
3035 for (int i = index; i< bucketActions.size(); i++) {
3036 Action action = bucketActions.get(i);
3037 if (action.getOrder() != i) {
3038 /* Shift the action order */
3039 ab = new ActionBuilder();
3040 ab.setAction(action.getAction());
3042 ab.setKey(new ActionKey(i));
3043 Action actionNewOrder = ab.build();
3044 bucketActions.remove(action);
3045 bucketActions.add(i, actionNewOrder);
3049 } else if (bucketActions.isEmpty()) {
3050 /* remove bucket with empty action list */
3051 buckets.getBucket().remove(bucket);
3055 if (!buckets.getBucket().isEmpty()) {
3056 /* rewrite the group to group table */
3057 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
3058 BucketsBuilder bucketsBuilder = new BucketsBuilder();
3059 List<Bucket> bucketList = Lists.newArrayList();
3060 BucketBuilder bucketBuilder = new BucketBuilder();
3061 bucketBuilder.setBucketId(new BucketId((long) 1));
3062 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
3063 bucketBuilder.setAction(bucketActions);
3064 bucketList.add(bucketBuilder.build());
3065 bucketsBuilder.setBucket(bucketList);
3066 groupBuilder.setBuckets(bucketsBuilder.build());
3067 logger.debug("removeOutputPortFromGroup: bucketList {}", bucketList);
3069 writeGroup(groupBuilder, nodeBuilder);
3070 ApplyActionsBuilder aab = new ApplyActionsBuilder();
3071 aab.setAction(actionList);
3072 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3075 /* remove group with empty bucket. return true to delete flow */
3076 removeGroup(groupBuilder, nodeBuilder);
3080 /* no group for port list. flow can be removed */
3086 public void initializeOFFlowRules(Node openflowNode) {
3087 Preconditions.checkNotNull(connectionService);
3088 List<Node> ovsNodes = connectionService.getNodes();
3089 if (ovsNodes == null) return;
3090 for (Node ovsNode : ovsNodes) {
3091 Long brIntDpid = this.getIntegrationBridgeOFDPID(ovsNode);
3092 Long brExDpid = this.getExternalBridgeDpid(ovsNode);
3093 logger.debug("Compare openflowNode to OVS node {} vs {} and {}", openflowNode.getID(), brIntDpid, brExDpid);
3094 String openflowID = openflowNode.getID().toString();
3095 if (openflowID.contains(brExDpid.toString())) {
3096 this.initializeFlowRules(ovsNode, configurationService.getExternalBridgeName());
3097 this.triggerInterfaceUpdates(ovsNode);
3099 if (openflowID.contains(brIntDpid.toString())) {
3100 this.initializeFlowRules(ovsNode, configurationService.getIntegrationBridgeName());
3101 this.triggerInterfaceUpdates(ovsNode);
3106 private NodeBuilder createNodeBuilder(String nodeId) {
3107 NodeBuilder builder = new NodeBuilder();
3108 builder.setId(new NodeId(nodeId));
3109 builder.setKey(new NodeKey(builder.getId()));
3113 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder
3115 return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
3116 node.getKey()).toInstance();
3119 private String getInternalBridgeUUID (Node node, String bridgeName) {
3120 Preconditions.checkNotNull(ovsdbConfigurationService);
3122 Map<String, Row> bridgeTable = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
3123 if (bridgeTable == null) return null;
3124 for (String key : bridgeTable.keySet()) {
3125 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(key));
3126 if (bridge.getName().equals(bridgeName)) return key;
3128 } catch (Exception e) {
3129 logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);