Bump versions by x.(y+1).z
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / OF13Provider.java
1 /**
2  * Copyright (C) 2013 Red Hat, Inc.
3  *
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
7  *
8  * Authors : Madhu Venugopal, Brent Salisbury, Dave Tucker
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt.providers;
11
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;
87
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;
93
94 import java.math.BigInteger;
95 import java.net.InetAddress;
96 import java.util.List;
97 import java.util.Map;
98 import java.util.Set;
99 import java.util.concurrent.ExecutionException;
100
101 /**
102  * Open vSwitch OpenFlow 1.3 Networking Provider for OpenStack Neutron
103  */
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;
112
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;
119
120     public OF13Provider(){
121
122     }
123
124     @Override
125     public boolean hasPerTenantTunneling() {
126         return false;
127     }
128
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);
134         }
135
136         if (!bridgeConfigurationManager.isNodeNeutronReady(node)) {
137             logger.error(node+" is not Overlay ready");
138             return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
139         }
140
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);
144         }
145         return new Status(StatusCode.SUCCESS);
146     }
147
148     private String getTunnelName(String tunnelType, InetAddress dst) {
149         return tunnelType+"-"+dst.getHostAddress();
150     }
151
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;
164             }
165         }
166         return false;
167     }
168
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();
181             }
182         }
183         return null;
184     }
185
186     private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
187         Preconditions.checkNotNull(ovsdbConfigurationService);
188         try {
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)) {
196                         bridgeUUID = uuid;
197                         break;
198                     }
199                 }
200             }
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);
204             }
205             String portName = getTunnelName(tunnelType, dst);
206
207             if (this.isTunnelPresent(node, portName, bridgeUUID)) {
208                 logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node);
209                 return new Status(StatusCode.SUCCESS);
210             }
211
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;
219             }
220
221             String tunnelPortUUID = statusWithUuid.getUuid().toString();
222             String interfaceUUID = null;
223             int timeout = 6;
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.
231                     Thread.sleep(500);
232                     timeout--;
233                     continue;
234                 }
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;
240             }
241
242             if (interfaceUUID == null) {
243                 logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID);
244                 return new Status(StatusCode.INTERNALERROR);
245             }
246
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);
257             return status;
258         } catch (Exception e) {
259             logger.error("Exception in addTunnelPort", e);
260             return new Status(StatusCode.INTERNALERROR);
261         }
262     }
263
264     /* delete port from ovsdb port table */
265     private Status deletePort(Node node, String bridgeName, String portName) {
266         Preconditions.checkNotNull(ovsdbConfigurationService);
267         try {
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)) {
274                         bridgeUUID = uuid;
275                         break;
276                     }
277                 }
278             }
279             if (bridgeUUID == null) {
280                 logger.debug("Could not find Bridge {} in {}", bridgeName, node);
281                 return new Status(StatusCode.SUCCESS);
282             }
283
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,
291                                 status);
292                    return status;
293                }
294                logger.debug("Port {} delete status : {}", portName, status);
295             }
296             return status;
297         } catch (Exception e) {
298             logger.error("Exception in deletePort", e);
299             return new Status(StatusCode.INTERNALERROR);
300         }
301     }
302
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);
307     }
308
309     private Status deletePhysicalPort(Node node, String phyIntfName) {
310         String intBridgeName = configurationService.getIntegrationBridgeName();
311         return deletePort(node, intBridgeName, phyIntfName);
312     }
313
314     private void programLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
315          /*
316          * Table(0) Rule #3
317          * ----------------
318          * Match: VM sMac and Local Ingress Port
319          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
320          */
321
322          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, true);
323
324         /*
325          * Table(0) Rule #4
326          * ----------------
327          * Match: Drop any remaining Ingress Local VM Packets
328          * Action: Drop w/ a low priority
329          */
330
331          handleDropSrcIface(dpid, localPort, true);
332
333          /*
334           * Table(2) Rule #1
335           * ----------------
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
339           */
340
341          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, true);
342
343          /*
344           * Table(2) Rule #2
345           * ----------------
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
349           */
350
351           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
352
353           /*
354            * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
355            */
356           /*
357            * Table(1) Rule #3
358            * ----------------
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
363            */
364
365            handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, true);
366
367           /*
368            * Table(2) Rule #3
369            * ----------------
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
373            */
374
375            handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, true);
376     }
377
378     private void removeLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
379         /*
380          * Table(0) Rule #3
381          * ----------------
382          * Match: VM sMac and Local Ingress Port
383          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
384          */
385
386          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, false);
387
388         /*
389          * Table(0) Rule #4
390          * ----------------
391          * Match: Drop any remaining Ingress Local VM Packets
392          * Action: Drop w/ a low priority
393          */
394
395          handleDropSrcIface(dpid, localPort, false);
396
397          /*
398           * Table(2) Rule #1
399           * ----------------
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
403           */
404
405          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, false);
406
407          /*
408           * Table(2) Rule #2
409           * ----------------
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
413           */
414
415           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
416     }
417
418     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
419         /*
420          * Table(0) Rule #2
421          * ----------------
422          * Match: Ingress Port, Tunnel ID
423          * Action: GOTO Local Table (20)
424          */
425
426          handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
427
428          /*
429           * Table(1) Rule #2
430           * ----------------
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
436           */
437
438          handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
439
440     }
441
442     private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
443         /*
444          * Table(1) Rule #1
445          * ----------------
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
451          */
452
453         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, true);
454     }
455
456     private void removeRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
457         /*
458          * Table(1) Rule #1
459          * ----------------
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
465          */
466
467         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, false);
468     }
469
470     /* Remove tunnel rules if last node in this tenant network */
471     private void removePerTunnelRules(Node node, Long dpid, String segmentationId, long tunnelOFPort) {
472         /*
473          * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
474          */
475         /*
476          * Table(1) Rule #3
477          * ----------------
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
482          */
483
484         handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, false);
485
486         /*
487          * Table(2) Rule #3
488          * ----------------
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
492          */
493
494         handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
495
496         /*
497          * Table(0) Rule #2
498          * ----------------
499          * Match: Ingress Port, Tunnel ID
500          * Action: GOTO Local Table (10)
501          */
502
503         handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
504
505          /*
506           * Table(1) Rule #2
507           * ----------------
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
513           */
514
515         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
516     }
517
518     private void programLocalVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
519         /*
520          * Table(0) Rule #1
521          * ----------------
522          * Match: VM sMac and Local Ingress Port
523          * Action: Set VLAN ID and GOTO Local Table 1
524          */
525
526         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
527                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
528                 attachedMac, true);
529
530         /*
531          * Table(0) Rule #3
532          * ----------------
533          * Match: Drop any remaining Ingress Local VM Packets
534          * Action: Drop w/ a low priority
535          */
536
537         handleDropSrcIface(dpid, localPort, true);
538
539         /*
540          * Table(2) Rule #1
541          * ----------------
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
545          */
546
547         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
548                 localPort, attachedMac, true);
549
550         /*
551          * Table(2) Rule #2
552          * ----------------
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
557          */
558
559         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
560                 localPort, true);
561
562          /*
563           * Table(2) Rule #3
564           * ----------------
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
568           */
569
570           handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
571                                    true);
572    }
573
574     private void removeLocalVlanRules(Node node, Long dpid,
575                                       String segmentationId, String attachedMac,
576                                       long localPort) {
577         /*
578          * Table(0) Rule #1
579          * ----------------
580          * Match: VM sMac and Local Ingress Port
581          * Action: Set VLAN ID and GOTO Local Table 1
582          */
583
584         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
585                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
586                 attachedMac, false);
587
588         /*
589          * Table(0) Rule #3
590          * ----------------
591          * Match: Drop any remaining Ingress Local VM Packets
592          * Action: Drop w/ a low priority
593          */
594
595         handleDropSrcIface(dpid, localPort, false);
596
597         /*
598          * Table(2) Rule #1
599          * ----------------
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
603          */
604
605         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
606                 localPort, attachedMac, false);
607
608         /*
609          * Table(2) Rule #2
610          * ----------------
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
615          */
616
617         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
618                 localPort, false);
619    }
620
621    private void programLocalIngressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
622        /*
623         * Table(0) Rule #2
624         * ----------------
625         * Match: Ingress port = physical interface, Vlan ID
626         * Action: GOTO Local Table 2
627         */
628
629        handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
630                     segmentationId, ethPort, true);
631
632         /*
633          * Table(1) Rule #2
634          * ----------------
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
640          */
641
642         handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
643                            segmentationId, ethPort, true);
644    }
645
646    private void programRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
647        /*
648         * Table(1) Rule #1
649         * ----------------
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
655         */
656
657        handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
658                      segmentationId, ethPort, attachedMac, true);
659
660        /*
661         * Table(1) Rule #3
662         * ----------------
663         * Match:  VLAN ID
664         * Action: Go to table 2
665         * -------------------------------------------
666         * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
667         */
668
669        handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
670                       segmentationId, ethPort, true);
671    }
672
673    private void removeRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
674        /*
675         * Table(1) Rule #1
676         * ----------------
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
682         */
683
684        handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
685                      segmentationId, ethPort, attachedMac, false);
686    }
687
688    private void removePerVlanRules(Node node, Long dpid, String segmentationId, long ethPort) {
689        /*
690         * Table(2) Rule #3
691         * ----------------
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
695         */
696
697         handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
698                                  false);
699
700         /*
701          * Table(0) Rule #2
702          * ----------------
703          * Match: Ingress port = physical interface, Vlan ID
704          * Action: GOTO Local Table 2
705          */
706
707         handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
708                      segmentationId, ethPort, false);
709
710          /*
711           * Table(1) Rule #2
712           * ----------------
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
718           */
719
720          handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
721                             segmentationId, ethPort, false);
722
723          /*
724           * Table(1) Rule #3
725           * ----------------
726           * Match:  VLAN ID
727           * Action: Go to table 2
728           * -------------------------------------------
729           * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
730           */
731
732          handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
733                         segmentationId, ethPort, false);
734    }
735     private Long getDpid (Node node, String bridgeUuid) {
736         Preconditions.checkNotNull(ovsdbConfigurationService);
737         try {
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);
746             return 0L;
747         }
748     }
749
750     private Long getIntegrationBridgeOFDPID (Node node) {
751         try {
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);
756                 return 0L;
757             }
758
759             return getDpid(node, brIntId);
760         } catch (Exception e) {
761             logger.error("Error finding Integration Bridge's OF DPID", e);
762             return 0L;
763         }
764     }
765
766     private Long getExternalBridgeDpid (Node node) {
767         try {
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);
772                 return 0L;
773             }
774
775             return getDpid(node, brUuid);
776         } catch (Exception e) {
777             logger.error("Error finding External Bridge's OF DPID", e);
778             return 0L;
779         }
780     }
781
782     private void programLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
783         try {
784             Long dpid = this.getIntegrationBridgeOFDPID(node);
785             if (dpid == 0L) {
786                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
787                 return;
788             }
789
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);
793                 return;
794             }
795             long localPort = (Long)of_ports.toArray()[0];
796
797             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
798             if (externalIds == null) {
799                 logger.error("No external_ids seen in {}", intf);
800                 return;
801             }
802
803             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
804             if (attachedMac == null) {
805                 logger.error("No AttachedMac seen in {}", intf);
806                 return;
807             }
808
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);
817             }
818         } catch (Exception e) {
819             logger.error("Exception in programming Local Rules for "+intf+" on "+node, e);
820         }
821     }
822
823     private void removeLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
824         try {
825             Long dpid = this.getIntegrationBridgeOFDPID(node);
826             if (dpid == 0L) {
827                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
828                 return;
829             }
830
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);
834                 return;
835             }
836             long localPort = (Long)of_ports.toArray()[0];
837
838             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
839             if (externalIds == null) {
840                 logger.error("No external_ids seen in {}", intf);
841                 return;
842             }
843
844             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
845             if (attachedMac == null) {
846                 logger.error("No AttachedMac seen in {}", intf);
847                 return;
848             }
849
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);
858             }
859         } catch (Exception e) {
860             logger.error("Exception in removing Local Rules for "+intf+" on "+node, e);
861         }
862     }
863
864     private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
865             Interface intf, boolean local) {
866
867         Preconditions.checkNotNull(ovsdbConfigurationService);
868
869         try {
870
871             Long dpid = this.getIntegrationBridgeOFDPID(node);
872             if (dpid == 0L) {
873                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
874                 return;
875             }
876
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);
880                 return;
881             }
882             long localPort = (Long)of_ports.toArray()[0];
883
884             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
885             if (externalIds == null) {
886                 logger.error("No external_ids seen in {}", intf);
887                 return;
888             }
889
890             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
891             if (attachedMac == null) {
892                 logger.error("No AttachedMac seen in {}", intf);
893                 return;
894             }
895
896             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
897             if (intfs != null) {
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);
904                             continue;
905                         }
906                         long tunnelOFPort = (Long)of_ports.toArray()[0];
907
908                         if (tunnelOFPort == -1) {
909                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
910                             return;
911                         }
912                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
913
914                         if (!local) {
915                             programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
916                         }
917                         logger.trace("program local ingress tunnel rules: node" + node.getNodeIDString() + " intf " + intf.getName());
918                         if (local) {
919                             programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
920                         }
921                         return;
922                     }
923                 }
924             }
925         } catch (Exception e) {
926             logger.error("", e);
927         }
928     }
929
930     private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
931             Interface intf, boolean local, boolean isLastInstanceOnNode) {
932
933         Preconditions.checkNotNull(ovsdbConfigurationService);
934         try {
935
936             Long dpid = this.getIntegrationBridgeOFDPID(node);
937             if (dpid == 0L) {
938                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
939                 return;
940             }
941
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);
945                 return;
946             }
947             long localPort = (Long)of_ports.toArray()[0];
948
949             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
950             if (externalIds == null) {
951                 logger.error("No external_ids seen in {}", intf);
952                 return;
953             }
954
955             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
956             if (attachedMac == null) {
957                 logger.error("No AttachedMac seen in {}", intf);
958                 return;
959             }
960
961             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
962             if (intfs != null) {
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);
969                             continue;
970                         }
971                         long tunnelOFPort = (Long)of_ports.toArray()[0];
972
973                         if (tunnelOFPort == -1) {
974                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
975                             return;
976                         }
977                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
978
979                         if (!local) {
980                             removeRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
981                         }
982                         if (local && isLastInstanceOnNode) {
983                             removePerTunnelRules(node, dpid, segmentationId, tunnelOFPort);
984                         }
985                         return;
986                     }
987                 }
988             }
989         } catch (Exception e) {
990             logger.error("", e);
991         }
992     }
993
994     private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
995         Preconditions.checkNotNull(ovsdbConfigurationService);
996         logger.debug("Program vlan rules for interface {}", intf.getName());
997         try {
998
999             Long dpid = this.getIntegrationBridgeOFDPID(node);
1000             if (dpid == 0L) {
1001                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1002                 return;
1003             }
1004
1005             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
1006             int timeout = 6;
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.
1011                     Thread.sleep(500);
1012                     timeout--;
1013                 }
1014             }
1015             if (of_ports == null || of_ports.size() <= 0) {
1016                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
1017                 return;
1018             }
1019
1020             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
1021             if (externalIds == null) {
1022                 logger.error("No external_ids seen in {}", intf);
1023                 return;
1024             }
1025
1026             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
1027             if (attachedMac == null) {
1028                 logger.error("No AttachedMac seen in {}", intf);
1029                 return;
1030             }
1031
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();
1038                         timeout = 6;
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.
1043                                 Thread.sleep(500);
1044                                 timeout--;
1045                             }
1046                         }
1047
1048                         if (of_ports == null || of_ports.size() <= 0) {
1049                             logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
1050                             continue;
1051                         }
1052                         long ethOFPort = (Long)of_ports.toArray()[0];
1053
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");
1057                         }
1058                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1059
1060                         programRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1061                         programLocalIngressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1062                         return;
1063                     }
1064                 }
1065             }
1066         } catch (Exception e) {
1067             logger.error("", e);
1068         }
1069     }
1070
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());
1075
1076         try {
1077
1078             Long dpid = this.getIntegrationBridgeOFDPID(node);
1079             if (dpid == 0L) {
1080                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1081                 return;
1082             }
1083
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);
1087                 return;
1088             }
1089
1090             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
1091             if (externalIds == null) {
1092                 logger.error("No external_ids seen in {}", intf);
1093                 return;
1094             }
1095
1096             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
1097             if (attachedMac == null) {
1098                 logger.error("No AttachedMac seen in {}", intf);
1099                 return;
1100             }
1101
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);
1111                             continue;
1112                         }
1113                         long ethOFPort = (Long)of_ports.toArray()[0];
1114
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");
1118                         }
1119                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1120
1121                         removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1122                         if (isLastInstanceOnNode) {
1123                             removePerVlanRules(node, dpid, network.getProviderSegmentationID(), ethOFPort);
1124                         }
1125                         return;
1126                     }
1127                 }
1128             }
1129         } catch (Exception e) {
1130             logger.error("", e);
1131         }
1132     }
1133
1134     @Override
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);
1140
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);
1151                 }
1152                 addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
1153                 if (status.isSuccess()) {
1154                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
1155                 }
1156             }
1157         }
1158
1159         return new Status(StatusCode.SUCCESS);
1160     }
1161
1162     private Status triggerInterfaceUpdates(Node node) {
1163         Preconditions.checkNotNull(ovsdbConfigurationService);
1164         try {
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);
1173                     }
1174                 }
1175             }
1176         } catch (Exception e) {
1177             logger.error("Error Triggering the lost interface updates for "+ node, e);
1178             return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage());
1179         }
1180         return new Status(StatusCode.SUCCESS);
1181     }
1182     @Override
1183     public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
1184         // TODO Auto-generated method stub
1185         return null;
1186     }
1187
1188     @Override
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);
1195
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 */
1201             try {
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);
1208             }
1209         } else if (phyIfName.contains(intf.getName())) {
1210             deletePhysicalPort(srcNode, intf.getName());
1211         } else {
1212             /* delete all other interfaces */
1213             this.removeLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(),
1214                     srcNode, intf);
1215
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)) {
1221
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);
1231                 }
1232             }
1233         }
1234         return status;
1235     }
1236
1237     @Override
1238     public void initializeFlowRules(Node node) {
1239         this.initializeFlowRules(node, configurationService.getIntegrationBridgeName());
1240         this.initializeFlowRules(node, configurationService.getExternalBridgeName());
1241         this.triggerInterfaceUpdates(node);
1242     }
1243
1244     private void initializeFlowRules(Node node, String bridgeName) {
1245         String bridgeUuid = this.getInternalBridgeUUID(node, bridgeName);
1246         if (bridgeUuid == null) {
1247             return;
1248         }
1249
1250         Long dpid = getDpid(node, bridgeUuid);
1251
1252         if (dpid == 0L) {
1253             logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1254             return;
1255         }
1256
1257         /*
1258          * Table(0) Rule #1
1259          * ----------------
1260          * Match: LLDP (0x88CCL)
1261          * Action: Packet_In to Controller Reserved Port
1262          */
1263
1264          writeLLDPRule(dpid);
1265          if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1266              writeNormalRule(dpid);
1267          }
1268     }
1269
1270     /*
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
1276     */
1277
1278     private void writeLLDPRule(Long dpidLong) {
1279
1280         String nodeName = OPENFLOW + dpidLong;
1281         EtherType etherType = new EtherType(0x88CCL);
1282
1283         MatchBuilder matchBuilder = new MatchBuilder();
1284         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1285         FlowBuilder flowBuilder = new FlowBuilder();
1286
1287         // Create Match(es) and Set them in the FlowBuilder Object
1288         flowBuilder.setMatch(OF13MdSalMatch.createEtherTypeMatch(matchBuilder, etherType).build());
1289
1290         // Create the OF Actions and Instructions
1291         InstructionBuilder ib = new InstructionBuilder();
1292         InstructionsBuilder isb = new InstructionsBuilder();
1293
1294         // Instructions List Stores Individual Instructions
1295         List<Instruction> instructions = Lists.newArrayList();
1296
1297         // Call the InstructionBuilder Methods Containing Actions
1298         OF13MdSalInstruction.createSendToControllerInstructions(ib);
1299         ib.setOrder(0);
1300         ib.setKey(new InstructionKey(0));
1301         instructions.add(ib.build());
1302
1303         // Add InstructionBuilder to the Instruction(s)Builder List
1304         isb.setInstruction(instructions);
1305
1306         // Add InstructionsBuilder to FlowBuilder
1307         flowBuilder.setInstructions(isb.build());
1308
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);
1319     }
1320
1321     /*
1322     * Create a NORMAL Table Miss Flow Rule
1323     * Match: any
1324     * Action: forward to NORMAL pipeline
1325     */
1326
1327     private void writeNormalRule(Long dpidLong) {
1328
1329         String nodeName = OPENFLOW + dpidLong;
1330
1331         MatchBuilder matchBuilder = new MatchBuilder();
1332         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1333         FlowBuilder flowBuilder = new FlowBuilder();
1334
1335         // Create the OF Actions and Instructions
1336         InstructionBuilder ib = new InstructionBuilder();
1337         InstructionsBuilder isb = new InstructionsBuilder();
1338
1339         // Instructions List Stores Individual Instructions
1340         List<Instruction> instructions = Lists.newArrayList();
1341
1342         // Call the InstructionBuilder Methods Containing Actions
1343         OF13MdSalInstruction.createNormalInstructions(ib);
1344         ib.setOrder(0);
1345         ib.setKey(new InstructionKey(0));
1346         instructions.add(ib.build());
1347
1348         // Add InstructionBuilder to the Instruction(s)Builder List
1349         isb.setInstruction(instructions);
1350
1351         // Add InstructionsBuilder to FlowBuilder
1352         flowBuilder.setInstructions(isb.build());
1353
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);
1366     }
1367
1368     /*
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
1373      */
1374
1375     private void handleTunnelIn(Long dpidLong, Short writeTable,
1376                                 Short goToTableId, String segmentationId,
1377                                 Long ofPort, boolean write) {
1378
1379         String nodeName = OPENFLOW + dpidLong;
1380
1381         BigInteger tunnelId = new BigInteger(segmentationId);
1382         MatchBuilder matchBuilder = new MatchBuilder();
1383         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1384         FlowBuilder flowBuilder = new FlowBuilder();
1385
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());
1389
1390         if (write) {
1391             // Create the OF Actions and Instructions
1392             InstructionBuilder ib = new InstructionBuilder();
1393             InstructionsBuilder isb = new InstructionsBuilder();
1394
1395             // Instructions List Stores Individual Instructions
1396             List<Instruction> instructions = Lists.newArrayList();
1397
1398             // Call the InstructionBuilder Methods Containing Actions
1399             OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1400             ib.setOrder(0);
1401             ib.setKey(new InstructionKey(0));
1402             instructions.add(ib.build());
1403
1404             // Add InstructionBuilder to the Instruction(s)Builder List
1405             isb.setInstruction(instructions);
1406
1407             // Add InstructionsBuilder to FlowBuilder
1408             flowBuilder.setInstructions(isb.build());
1409         }
1410
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);
1422
1423         if (write) {
1424             writeFlow(flowBuilder, nodeBuilder);
1425         } else {
1426             removeFlow(flowBuilder, nodeBuilder);
1427         }
1428     }
1429
1430     /*
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
1435      */
1436
1437     private void handleVlanIn(Long dpidLong, Short writeTable, Short goToTableId,
1438                       String segmentationId,  Long ethPort, boolean write) {
1439
1440         String nodeName = OPENFLOW + dpidLong;
1441
1442         MatchBuilder matchBuilder = new MatchBuilder();
1443         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1444         FlowBuilder flowBuilder = new FlowBuilder();
1445
1446         // Create Match(es) and Set them in the FlowBuilder Object
1447         flowBuilder.setMatch(
1448                 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)))
1449                         .build())
1450                 .setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, ethPort)
1451                         .build());
1452
1453         if (write) {
1454             // Create the OF Actions and Instructions
1455             InstructionBuilder ib = new InstructionBuilder();
1456             InstructionsBuilder isb = new InstructionsBuilder();
1457
1458             // Instructions List Stores Individual Instructions
1459             List<Instruction> instructions = Lists.newArrayList();
1460
1461             // Call the InstructionBuilder Methods Containing Actions
1462             OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1463             ib.setOrder(0);
1464             ib.setKey(new InstructionKey(0));
1465             instructions.add(ib.build());
1466
1467             // Add InstructionBuilder to the Instruction(s)Builder List
1468             isb.setInstruction(instructions);
1469
1470             // Add InstructionsBuilder to FlowBuilder
1471             flowBuilder.setInstructions(isb.build());
1472         }
1473
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);
1485         if (write) {
1486             writeFlow(flowBuilder, nodeBuilder);
1487         } else {
1488             removeFlow(flowBuilder, nodeBuilder);
1489         }
1490     }
1491
1492    /*
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"
1498     */
1499
1500     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
1501                            String segmentationId, Long inPort, String attachedMac,
1502                            boolean write) {
1503
1504         String nodeName = OPENFLOW + dpidLong;
1505
1506         MatchBuilder matchBuilder = new MatchBuilder();
1507         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1508         FlowBuilder flowBuilder = new FlowBuilder();
1509
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());
1514
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);
1526
1527         if (write) {
1528             // Instantiate the Builders for the OF Actions and Instructions
1529             InstructionBuilder ib = new InstructionBuilder();
1530             InstructionsBuilder isb = new InstructionsBuilder();
1531
1532             // Instructions List Stores Individual Instructions
1533             List<Instruction> instructions = Lists.newArrayList();
1534
1535             // GOTO Instructions Need to be added first to the List
1536             OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1537             ib.setOrder(0);
1538             ib.setKey(new InstructionKey(0));
1539             instructions.add(ib.build());
1540             // TODO Broken SetTunID
1541             OF13MdSalInstruction.createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
1542             ib.setOrder(1);
1543             ib.setKey(new InstructionKey(1));
1544             instructions.add(ib.build());
1545
1546             // Add InstructionBuilder to the Instruction(s)Builder List
1547             isb.setInstruction(instructions);
1548
1549             // Add InstructionsBuilder to FlowBuilder
1550             flowBuilder.setInstructions(isb.build());
1551
1552             writeFlow(flowBuilder, nodeBuilder);
1553         } else {
1554             removeFlow(flowBuilder, nodeBuilder);
1555         }
1556     }
1557
1558     /*
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"
1564      */
1565
1566      private void handleLocalInPortSetVlan(Long dpidLong, Short writeTable,
1567                                   Short goToTableId, String segmentationId,
1568                                   Long inPort, String attachedMac,
1569                                   boolean write) {
1570
1571          String nodeName = OPENFLOW + dpidLong;
1572
1573          MatchBuilder matchBuilder = new MatchBuilder();
1574          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1575          FlowBuilder flowBuilder = new FlowBuilder();
1576
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());
1580
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);
1592
1593          if (write) {
1594              // Instantiate the Builders for the OF Actions and Instructions
1595              InstructionBuilder ib = new InstructionBuilder();
1596              InstructionsBuilder isb = new InstructionsBuilder();
1597
1598              // Instructions List Stores Individual Instructions
1599              List<Instruction> instructions = Lists.newArrayList();
1600
1601              // GOTO Instructions Need to be added first to the List
1602              OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1603              ib.setOrder(0);
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)));
1608              ib.setOrder(1);
1609              ib.setKey(new InstructionKey(1));
1610              instructions.add(ib.build());
1611
1612              // Add InstructionBuilder to the Instruction(s)Builder List
1613              isb.setInstruction(instructions);
1614
1615              // Add InstructionsBuilder to FlowBuilder
1616              flowBuilder.setInstructions(isb.build());
1617
1618              writeFlow(flowBuilder, nodeBuilder);
1619          } else {
1620              removeFlow(flowBuilder, nodeBuilder);
1621          }
1622      }
1623
1624     /*
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
1628      * Instruction: Drop
1629      * table=0,priority=16384,in_port=1 actions=drop"
1630      */
1631
1632     private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
1633
1634         String nodeName = OPENFLOW + dpidLong;
1635
1636         MatchBuilder matchBuilder = new MatchBuilder();
1637         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1638         FlowBuilder flowBuilder = new FlowBuilder();
1639
1640         // Create the OF Match using MatchBuilder
1641         flowBuilder.setMatch(OF13MdSalMatch.createInPortMatch(matchBuilder, dpidLong, inPort).build());
1642
1643         if (write) {
1644             // Instantiate the Builders for the OF Actions and Instructions
1645             InstructionBuilder ib = new InstructionBuilder();
1646             InstructionsBuilder isb = new InstructionsBuilder();
1647
1648             // Instructions List Stores Individual Instructions
1649             List<Instruction> instructions = Lists.newArrayList();
1650
1651             // Call the InstructionBuilder Methods Containing Actions
1652             OF13MdSalInstruction.createDropInstructions(ib);
1653             ib.setOrder(0);
1654             ib.setKey(new InstructionKey(0));
1655             instructions.add(ib.build());
1656
1657             // Add InstructionBuilder to the Instruction(s)Builder List
1658             isb.setInstruction(instructions);
1659
1660             // Add InstructionsBuilder to FlowBuilder
1661             flowBuilder.setInstructions(isb.build());
1662         }
1663
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);
1676         if (write) {
1677             writeFlow(flowBuilder, nodeBuilder);
1678         } else {
1679             removeFlow(flowBuilder, nodeBuilder);
1680         }
1681     }
1682
1683    /*
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"
1689     */
1690     private void handleTunnelOut(Long dpidLong, Short writeTable,
1691                          Short goToTableId, String segmentationId,
1692                          Long OFPortOut, String attachedMac,
1693                          boolean write) {
1694
1695         String nodeName = OPENFLOW + dpidLong;
1696
1697         MatchBuilder matchBuilder = new MatchBuilder();
1698         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1699         FlowBuilder flowBuilder = new FlowBuilder();
1700
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());
1704
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);
1716
1717         if (write) {
1718             // Instantiate the Builders for the OF Actions and Instructions
1719             InstructionBuilder ib = new InstructionBuilder();
1720             InstructionsBuilder isb = new InstructionsBuilder();
1721
1722             // Instructions List Stores Individual Instructions
1723             List<Instruction> instructions = Lists.newArrayList();
1724
1725             // GOTO Instructions
1726             OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1727             ib.setOrder(0);
1728             ib.setKey(new InstructionKey(0));
1729             instructions.add(ib.build());
1730             // Set the Output Port/Iface
1731             OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, OFPortOut);
1732             ib.setOrder(1);
1733             ib.setKey(new InstructionKey(1));
1734             instructions.add(ib.build());
1735
1736             // Add InstructionBuilder to the Instruction(s)Builder List
1737             isb.setInstruction(instructions);
1738
1739             // Add InstructionsBuilder to FlowBuilder
1740             flowBuilder.setInstructions(isb.build());
1741
1742             writeFlow(flowBuilder, nodeBuilder);
1743         } else {
1744             removeFlow(flowBuilder, nodeBuilder);
1745         }
1746     }
1747
1748     /*
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"
1754      */
1755
1756      private void handleVlanOut(Long dpidLong, Short writeTable,
1757                         Short goToTableId, String segmentationId,
1758                         Long ethPort, String attachedMac, boolean write) {
1759
1760          String nodeName = OPENFLOW + dpidLong;
1761
1762          MatchBuilder matchBuilder = new MatchBuilder();
1763          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1764          FlowBuilder flowBuilder = new FlowBuilder();
1765
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());
1770
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);
1782
1783          if (write) {
1784              // Instantiate the Builders for the OF Actions and Instructions
1785              InstructionBuilder ib = new InstructionBuilder();
1786              InstructionsBuilder isb = new InstructionsBuilder();
1787
1788              // Instructions List Stores Individual Instructions
1789              List<Instruction> instructions = Lists.newArrayList();
1790
1791              // GOTO Instructions
1792              OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
1793              ib.setOrder(0);
1794              ib.setKey(new InstructionKey(0));
1795              instructions.add(ib.build());
1796
1797              // Add InstructionBuilder to the Instruction(s)Builder List
1798              isb.setInstruction(instructions);
1799
1800              // Add InstructionsBuilder to FlowBuilder
1801              flowBuilder.setInstructions(isb.build());
1802
1803              writeFlow(flowBuilder, nodeBuilder);
1804          } else {
1805              removeFlow(flowBuilder, nodeBuilder);
1806          }
1807      }
1808
1809        /*
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
1815     */
1816
1817     private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
1818                              Short localTable, String segmentationId,
1819                              Long OFPortOut, boolean write) {
1820
1821         String nodeName = OPENFLOW + dpidLong;
1822
1823         MatchBuilder matchBuilder = new MatchBuilder();
1824         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1825         FlowBuilder flowBuilder = new FlowBuilder();
1826
1827         // Create the OF Match using MatchBuilder
1828         // Match TunnelID
1829         flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1830         // Match DMAC
1831
1832         flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
1833                 new MacAddress("01:00:00:00:00:00")).build());
1834
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);
1846
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;
1853         if (flow != null) {
1854             Instructions ins = flow.getInstructions();
1855             if (ins != null) {
1856                 existingInstructions = ins.getInstruction();
1857             }
1858         }
1859
1860         if (write) {
1861             // GOTO Instruction
1862             OF13MdSalInstruction.createGotoTableInstructions(ib, localTable);
1863             ib.setOrder(0);
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);
1869             ib.setOrder(1);
1870             ib.setKey(new InstructionKey(1));
1871             instructions.add(ib.build());
1872
1873             // Add InstructionBuilder to the Instruction(s)Builder List
1874             isb.setInstruction(instructions);
1875
1876             // Add InstructionsBuilder to FlowBuilder
1877             flowBuilder.setInstructions(isb.build());
1878
1879             writeFlow(flowBuilder, nodeBuilder);
1880         } else {
1881             /* remove port from action list */
1882             boolean flowRemove = OF13MdSalInstruction.removeOutputPortFromInstructions(ib, dpidLong,
1883                     OFPortOut, existingInstructions);
1884             if (flowRemove) {
1885                 /* if all port are removed, remove the flow too. */
1886                 removeFlow(flowBuilder, nodeBuilder);
1887             } else {
1888                 /* Install instruction with new output port list*/
1889                 ib.setOrder(0);
1890                 ib.setKey(new InstructionKey(0));
1891                 instructions.add(ib.build());
1892
1893                 // Add InstructionBuilder to the Instruction(s)Builder List
1894                 isb.setInstruction(instructions);
1895
1896                 // Add InstructionsBuilder to FlowBuilder
1897                 flowBuilder.setInstructions(isb.build());
1898             }
1899         }
1900     }
1901
1902     /*
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
1908      */
1909
1910      private void handleVlanFloodOut(Long dpidLong, Short writeTable,
1911                            Short localTable, String segmentationId,
1912                            Long ethPort, boolean write) {
1913
1914          String nodeName = OPENFLOW + dpidLong;
1915
1916          MatchBuilder matchBuilder = new MatchBuilder();
1917          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1918          FlowBuilder flowBuilder = new FlowBuilder();
1919
1920          // Create the OF Match using MatchBuilder
1921          // Match Vlan ID
1922          flowBuilder.setMatch(
1923                  OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
1924          // Match DMAC
1925          flowBuilder.setMatch(OF13MdSalMatch.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
1926                  new MacAddress("01:00:00:00:00:00")).build());
1927
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);
1939
1940          //ToDo: Is there something to be done with result of the call to getFlow?
1941
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();
1947
1948          if (write) {
1949              // GOTO Instruction
1950              OF13MdSalInstruction.createGotoTableInstructions(ib, localTable);
1951              ib.setOrder(0);
1952              ib.setKey(new InstructionKey(0));
1953              instructions.add(ib.build());
1954              // Set the Output Port/Iface
1955              OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, ethPort);
1956              ib.setOrder(1);
1957              ib.setKey(new InstructionKey(1));
1958              instructions.add(ib.build());
1959
1960              // Add InstructionBuilder to the Instruction(s)Builder List
1961              isb.setInstruction(instructions);
1962
1963              // Add InstructionsBuilder to FlowBuilder
1964              flowBuilder.setInstructions(isb.build());
1965
1966              writeFlow(flowBuilder, nodeBuilder);
1967          } else {
1968              removeFlow(flowBuilder, nodeBuilder);
1969          }
1970      }
1971
1972    /*
1973     * (Table:1) Table Drain w/ Catch All
1974     * Match: Tunnel ID
1975     * Action: GOTO Local Table (10)
1976     * table=2,priority=8192,tun_id=0x5 actions=drop
1977     */
1978
1979     private void handleTunnelMiss(Long dpidLong, Short writeTable,
1980                           Short goToTableId, String segmentationId,
1981                           boolean write) {
1982
1983         String nodeName = OPENFLOW + dpidLong;
1984
1985         MatchBuilder matchBuilder = new MatchBuilder();
1986         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1987         FlowBuilder flowBuilder = new FlowBuilder();
1988
1989         // Create Match(es) and Set them in the FlowBuilder Object
1990         flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1991
1992         if (write) {
1993             // Create the OF Actions and Instructions
1994             InstructionBuilder ib = new InstructionBuilder();
1995             InstructionsBuilder isb = new InstructionsBuilder();
1996
1997             // Instructions List Stores Individual Instructions
1998             List<Instruction> instructions = Lists.newArrayList();
1999
2000             // Call the InstructionBuilder Methods Containing Actions
2001             OF13MdSalInstruction.createGotoTableInstructions(ib, goToTableId);
2002             ib.setOrder(0);
2003             ib.setKey(new InstructionKey(0));
2004             instructions.add(ib.build());
2005
2006             // Add InstructionBuilder to the Instruction(s)Builder List
2007             isb.setInstruction(instructions);
2008
2009             // Add InstructionsBuilder to FlowBuilder
2010             flowBuilder.setInstructions(isb.build());
2011         }
2012
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);
2025         if (write) {
2026             writeFlow(flowBuilder, nodeBuilder);
2027         } else {
2028             removeFlow(flowBuilder, nodeBuilder);
2029         }
2030     }
2031
2032
2033     /*
2034      * (Table:1) Table Drain w/ Catch All
2035      * Match: Vlan ID
2036      * Action: Output port eth interface
2037      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
2038      */
2039
2040      private void handleVlanMiss(Long dpidLong, Short writeTable,
2041                          Short goToTableId, String segmentationId,
2042                          Long ethPort, boolean write) {
2043
2044          String nodeName = OPENFLOW + dpidLong;
2045
2046          MatchBuilder matchBuilder = new MatchBuilder();
2047          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2048          FlowBuilder flowBuilder = new FlowBuilder();
2049
2050          // Create Match(es) and Set them in the FlowBuilder Object
2051          flowBuilder.setMatch(
2052                  OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2053
2054          if (write) {
2055              // Create the OF Actions and Instructions
2056              InstructionBuilder ib = new InstructionBuilder();
2057              InstructionsBuilder isb = new InstructionsBuilder();
2058
2059              // Instructions List Stores Individual Instructions
2060              List<Instruction> instructions = Lists.newArrayList();
2061
2062              // Call the InstructionBuilder Methods Containing Actions
2063              //createGotoTableInstructions(ib, goToTableId);
2064              //ib.setOrder(0);
2065              //ib.setKey(new InstructionKey(0));
2066              //instructions.add(ib.build());
2067              // Set the Output Port/Iface
2068              OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, ethPort);
2069              ib.setOrder(0);
2070              ib.setKey(new InstructionKey(1));
2071              instructions.add(ib.build());
2072
2073              // Add InstructionBuilder to the Instruction(s)Builder List
2074              isb.setInstruction(instructions);
2075
2076              // Add InstructionsBuilder to FlowBuilder
2077              flowBuilder.setInstructions(isb.build());
2078          }
2079
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);
2092          if (write) {
2093              writeFlow(flowBuilder, nodeBuilder);
2094          } else {
2095              removeFlow(flowBuilder, nodeBuilder);
2096          }
2097      }
2098
2099     /*
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
2104      */
2105
2106     private void handleLocalUcastOut(Long dpidLong, Short writeTable,
2107                              String segmentationId, Long localPort,
2108                              String attachedMac, boolean write) {
2109
2110         String nodeName = OPENFLOW + dpidLong;
2111
2112         MatchBuilder matchBuilder = new MatchBuilder();
2113         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2114         FlowBuilder flowBuilder = new FlowBuilder();
2115
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());
2119
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);
2131
2132         if (write) {
2133             // Instantiate the Builders for the OF Actions and Instructions
2134             InstructionBuilder ib = new InstructionBuilder();
2135             InstructionsBuilder isb = new InstructionsBuilder();
2136
2137             // Instructions List Stores Individual Instructions
2138             List<Instruction> instructions = Lists.newArrayList();
2139
2140             // Set the Output Port/Iface
2141             OF13MdSalInstruction.createOutputPortInstructions(ib, dpidLong, localPort);
2142             ib.setOrder(0);
2143             ib.setKey(new InstructionKey(0));
2144             instructions.add(ib.build());
2145
2146             // Add InstructionBuilder to the Instruction(s)Builder List
2147             isb.setInstruction(instructions);
2148
2149             // Add InstructionsBuilder to FlowBuilder
2150             flowBuilder.setInstructions(isb.build());
2151             writeFlow(flowBuilder, nodeBuilder);
2152         } else {
2153             removeFlow(flowBuilder, nodeBuilder);
2154         }
2155     }
2156
2157     /*
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
2162      */
2163
2164     private void handleLocalVlanUcastOut(Long dpidLong, Short writeTable,
2165                                  String segmentationId, Long localPort,
2166                                  String attachedMac, boolean write) {
2167
2168         String nodeName = OPENFLOW + dpidLong;
2169
2170         MatchBuilder matchBuilder = new MatchBuilder();
2171         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2172         FlowBuilder flowBuilder = new FlowBuilder();
2173
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());
2178
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);
2190
2191         if (write) {
2192             // Instantiate the Builders for the OF Actions and Instructions
2193             InstructionBuilder ib = new InstructionBuilder();
2194             InstructionsBuilder isb = new InstructionsBuilder();
2195
2196             // Instructions List Stores Individual Instructions
2197             List<Instruction> instructions = Lists.newArrayList();
2198             List<Instruction> instructions_tmp = Lists.newArrayList();
2199
2200             /* Strip vlan and store to tmp instruction space*/
2201             OF13MdSalInstruction.createPopVlanInstructions(ib);
2202             ib.setOrder(0);
2203             ib.setKey(new InstructionKey(0));
2204             instructions_tmp.add(ib.build());
2205
2206             // Set the Output Port/Iface
2207             ib = new InstructionBuilder();
2208             OF13MdSalInstruction.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
2209             ib.setOrder(0);
2210             ib.setKey(new InstructionKey(0));
2211             instructions.add(ib.build());
2212
2213             // Add InstructionBuilder to the Instruction(s)Builder List
2214             isb.setInstruction(instructions);
2215
2216             // Add InstructionsBuilder to FlowBuilder
2217             flowBuilder.setInstructions(isb.build());
2218             writeFlow(flowBuilder, nodeBuilder);
2219         } else {
2220             removeFlow(flowBuilder, nodeBuilder);
2221         }
2222     }
2223
2224     /*
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
2229      */
2230
2231     private void handleLocalBcastOut(Long dpidLong, Short writeTable,
2232                              String segmentationId, Long localPort,
2233                              boolean write) {
2234
2235         String nodeName = OPENFLOW + dpidLong;
2236
2237         MatchBuilder matchBuilder = new MatchBuilder();
2238         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2239         FlowBuilder flowBuilder = new FlowBuilder();
2240
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());
2245
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;
2264         if (flow != null) {
2265             Instructions ins = flow.getInstructions();
2266             if (ins != null) {
2267                 existingInstructions = ins.getInstruction();
2268             }
2269         }
2270
2271         if (write) {
2272             // Create output port list
2273             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
2274             ib.setOrder(0);
2275             ib.setKey(new InstructionKey(0));
2276             instructions.add(ib.build());
2277
2278             // Add InstructionBuilder to the Instruction(s)Builder List
2279             isb.setInstruction(instructions);
2280
2281             // Add InstructionsBuilder to FlowBuilder
2282             flowBuilder.setInstructions(isb.build());
2283
2284             writeFlow(flowBuilder, nodeBuilder);
2285         } else {
2286             boolean flowRemove = OF13MdSalInstruction.removeOutputPortFromInstructions(ib, dpidLong, localPort,
2287                     existingInstructions);
2288             if (flowRemove) {
2289                 /* if all ports are removed, remove flow */
2290                 removeFlow(flowBuilder, nodeBuilder);
2291             } else {
2292                 /* Install instruction with new output port list*/
2293                 ib.setOrder(0);
2294                 ib.setKey(new InstructionKey(0));
2295                 instructions.add(ib.build());
2296
2297                 // Add InstructionBuilder to the Instruction(s)Builder List
2298                 isb.setInstruction(instructions);
2299
2300                 // Add InstructionsBuilder to FlowBuilder
2301                 flowBuilder.setInstructions(isb.build());
2302
2303                 writeFlow(flowBuilder, nodeBuilder);
2304             }
2305         }
2306     }
2307
2308     /*
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
2313      */
2314
2315     private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable,
2316                                  String segmentationId, Long localPort,
2317                                  boolean write) {
2318
2319         String nodeName = OPENFLOW + dpidLong;
2320
2321         MatchBuilder matchBuilder = new MatchBuilder();
2322         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2323         FlowBuilder flowBuilder = new FlowBuilder();
2324
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());
2330
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;
2350         if (flow != null) {
2351             Instructions ins = flow.getInstructions();
2352             if (ins != null) {
2353                 existingInstructions = ins.getInstruction();
2354             }
2355         }
2356
2357         if (write) {
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;
2367                             break;
2368                         }
2369                     }
2370                 }
2371             } else {
2372                 existingInstructions = Lists.newArrayList();
2373             }
2374
2375             if (add_pop_vlan) {
2376                 /* pop vlan */
2377                 OF13MdSalInstruction.createPopVlanInstructions(ib);
2378                 ib.setOrder(0);
2379                 ib.setKey(new InstructionKey(0));
2380                 existingInstructions.add(ib.build());
2381                 ib = new InstructionBuilder();
2382             }
2383
2384             // Create port list
2385             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, localPort, existingInstructions);
2386             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
2387             ib.setOrder(0);
2388             ib.setKey(new InstructionKey(0));
2389             instructions.add(ib.build());
2390
2391             // Add InstructionBuilder to the Instruction(s)Builder List
2392             isb.setInstruction(instructions);
2393
2394             // Add InstructionsBuilder to FlowBuilder
2395             flowBuilder.setInstructions(isb.build());
2396
2397             writeFlow(flowBuilder, nodeBuilder);
2398         } else {
2399             //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
2400             //                     localPort, existingInstructions);
2401             boolean flowRemove = OF13MdSalInstruction.removeOutputPortFromInstructions(ib, dpidLong,
2402                     localPort, existingInstructions);
2403             if (flowRemove) {
2404                 /* if all ports are removed, remove flow */
2405                 removeFlow(flowBuilder, nodeBuilder);
2406             } else {
2407                 /* Install instruction with new output port list*/
2408                 ib.setOrder(0);
2409                 ib.setKey(new InstructionKey(0));
2410                 instructions.add(ib.build());
2411
2412                 // Add InstructionBuilder to the Instruction(s)Builder List
2413                 isb.setInstruction(instructions);
2414
2415                 // Add InstructionsBuilder to FlowBuilder
2416                 flowBuilder.setInstructions(isb.build());
2417                 writeFlow(flowBuilder, nodeBuilder);
2418             }
2419         }
2420     }
2421
2422     /*
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
2427      */
2428
2429     private void handleLocalTableMiss(Long dpidLong, Short writeTable,
2430                              String segmentationId, boolean write) {
2431
2432         String nodeName = OPENFLOW + dpidLong;
2433
2434         MatchBuilder matchBuilder = new MatchBuilder();
2435         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2436         FlowBuilder flowBuilder = new FlowBuilder();
2437
2438         // Create Match(es) and Set them in the FlowBuilder Object
2439         flowBuilder.setMatch(OF13MdSalMatch.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2440
2441         if (write) {
2442             // Create the OF Actions and Instructions
2443             InstructionBuilder ib = new InstructionBuilder();
2444             InstructionsBuilder isb = new InstructionsBuilder();
2445
2446             // Instructions List Stores Individual Instructions
2447             List<Instruction> instructions = Lists.newArrayList();
2448
2449             // Call the InstructionBuilder Methods Containing Actions
2450             OF13MdSalInstruction.createDropInstructions(ib);
2451             ib.setOrder(0);
2452             ib.setKey(new InstructionKey(0));
2453             instructions.add(ib.build());
2454
2455             // Add InstructionBuilder to the Instruction(s)Builder List
2456             isb.setInstruction(instructions);
2457
2458             // Add InstructionsBuilder to FlowBuilder
2459             flowBuilder.setInstructions(isb.build());
2460         }
2461
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);
2474         if (write) {
2475             writeFlow(flowBuilder, nodeBuilder);
2476         } else {
2477             removeFlow(flowBuilder, nodeBuilder);
2478         }
2479     }
2480
2481     /*
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
2486      */
2487
2488     private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
2489                                   String segmentationId, boolean write) {
2490
2491         String nodeName = OPENFLOW + dpidLong;
2492
2493         MatchBuilder matchBuilder = new MatchBuilder();
2494         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2495         FlowBuilder flowBuilder = new FlowBuilder();
2496
2497         // Create Match(es) and Set them in the FlowBuilder Object
2498         flowBuilder.setMatch(
2499                 OF13MdSalMatch.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2500
2501         if (write) {
2502             // Create the OF Actions and Instructions
2503             InstructionBuilder ib = new InstructionBuilder();
2504             InstructionsBuilder isb = new InstructionsBuilder();
2505
2506             // Instructions List Stores Individual Instructions
2507             List<Instruction> instructions = Lists.newArrayList();
2508
2509             // Call the InstructionBuilder Methods Containing Actions
2510             OF13MdSalInstruction.createDropInstructions(ib);
2511             ib.setOrder(0);
2512             ib.setKey(new InstructionKey(0));
2513             instructions.add(ib.build());
2514
2515             // Add InstructionBuilder to the Instruction(s)Builder List
2516             isb.setInstruction(instructions);
2517
2518             // Add InstructionsBuilder to FlowBuilder
2519             flowBuilder.setInstructions(isb.build());
2520         }
2521
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);
2534         if (write) {
2535             writeFlow(flowBuilder, nodeBuilder);
2536         } else {
2537             removeFlow(flowBuilder, nodeBuilder);
2538         }
2539     }
2540
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 ?");
2545             return null;
2546         }
2547
2548         dataBroker = mdsalConsumer.getDataBroker();
2549         if (dataBroker == null) {
2550             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2551             return null;
2552         }
2553
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();
2558         try {
2559             Optional<Group> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
2560             if (data.isPresent()) {
2561                 return data.get();
2562             }
2563         } catch (InterruptedException|ExecutionException e) {
2564             logger.error(e.getMessage(), e);
2565         }
2566
2567         logger.debug("Cannot find data for Group " + groupBuilder.getGroupName());
2568         return null;
2569     }
2570
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 ?");
2575             return;
2576         }
2577
2578         dataBroker = mdsalConsumer.getDataBroker();
2579         if (dataBroker == null) {
2580             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2581             return;
2582         }
2583
2584         ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
2585
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();
2589         try {
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()+")");
2593                 return;
2594             }
2595         } catch (InterruptedException|ExecutionException e) {
2596             logger.error(e.getMessage(), e);
2597             return;
2598         }
2599
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*/);
2604
2605         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2606         try {
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);
2611         }
2612     }
2613
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 ?");
2618             return;
2619         }
2620
2621         dataBroker = mdsalConsumer.getDataBroker();
2622         if (dataBroker == null) {
2623             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2624             return;
2625         }
2626
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();
2633
2634         try {
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);
2639         }
2640     }
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 ?");
2645             return null;
2646         }
2647
2648         dataBroker = mdsalConsumer.getDataBroker();
2649         if (dataBroker == null) {
2650             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2651             return null;
2652         }
2653
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();
2657
2658         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
2659         try {
2660             Optional<Flow> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
2661             if (data.isPresent()) {
2662                 return data.get();
2663             }
2664         } catch (InterruptedException|ExecutionException e) {
2665             logger.error(e.getMessage(), e);
2666         }
2667
2668         logger.debug("Cannot find data for Flow " + flowBuilder.getFlowName());
2669         return null;
2670     }
2671
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 ?");
2676             return;
2677         }
2678
2679         dataBroker = mdsalConsumer.getDataBroker();
2680         if (dataBroker == null) {
2681             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2682             return;
2683         }
2684
2685         ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
2686
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();
2690         try {
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()+")");
2694                 return;
2695             }
2696         } catch (InterruptedException|ExecutionException e) {
2697             logger.error(e.getMessage(), e);
2698             return;
2699         }
2700
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();
2704
2705         //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
2706         modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(), true /*createMissingParents*/);
2707
2708
2709         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2710         try {
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);
2715         }
2716     }
2717
2718     private void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2719         Preconditions.checkNotNull(mdsalConsumer);
2720         if (mdsalConsumer == null) {
2721             logger.error("ERROR finding MDSAL Service.");
2722             return;
2723         }
2724
2725         dataBroker = mdsalConsumer.getDataBroker();
2726         if (dataBroker == null) {
2727             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2728             return;
2729         }
2730
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);
2741
2742         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2743         try {
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);
2748         }
2749     }
2750
2751     /**
2752      * Create Output Port Group Instruction
2753      *
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
2758      */
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);
2764
2765         List<Action> actionList = Lists.newArrayList();
2766         ActionBuilder ab = new ActionBuilder();
2767
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);
2774                 }
2775             }
2776         }
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;
2782
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))) {
2789                     addNew = false;
2790                     break;
2791                 }
2792             }
2793         }
2794         if (addNew) {
2795             ab.setOrder(actionList.size());
2796             ab.setKey(new ActionKey(actionList.size()));
2797             actionList.add(ab.build());
2798         }
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());
2804         return ib;
2805     }
2806
2807     /**
2808      * Create Output Port Group Instruction
2809      *
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
2814      */
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);
2821
2822         List<Action> actionList = Lists.newArrayList();
2823         ActionBuilder ab = new ActionBuilder();
2824
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);
2831                 }
2832             }
2833         }
2834
2835         GroupBuilder groupBuilder = new GroupBuilder();
2836         Group group = null;
2837
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;
2845
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));
2854
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);
2861                 break;
2862             }
2863         }
2864
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))) {
2878                             addNew = false;
2879                             break;
2880                         }
2881                     }
2882                 }
2883             }
2884             logger.debug("createOutputGroupInstructions: addNew {}", addNew);
2885             if (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());
2895
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);
2907                 }
2908             }
2909         } else {
2910             /* create group */
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);
2917
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)));
2923
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());
2930
2931             bucket.setAction(bucketActionList);
2932             bucketList.add(bucket.build());
2933             bucketBuilder.setBucket(bucketList);
2934             groupBuilder.setBuckets(bucketBuilder.build());
2935
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());
2945
2946             groupId++;
2947         }
2948         logger.debug("createOutputGroupInstructions: group {}", groupBuilder.build());
2949         logger.debug("createOutputGroupInstructions: actionList {}", actionList);
2950
2951         if (addNew) {
2952             /* rewrite the group to group table */
2953             writeGroup(groupBuilder, nodeBuilder);
2954         }
2955
2956         // Create an Apply Action
2957         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2958         aab.setAction(actionList);
2959         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2960
2961         return ib;
2962     }
2963
2964     /**
2965      * Remove Output Port from action list in group bucket
2966      *
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
2971      */
2972     protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
2973                                 Long dpidLong, Long port , List<Instruction> instructions) {
2974
2975         NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
2976         logger.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
2977
2978         List<Action> actionList = Lists.newArrayList();
2979         ActionBuilder ab;
2980
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);
2987                     break;
2988                 }
2989             }
2990         }
2991
2992         GroupBuilder groupBuilder = new GroupBuilder();
2993         Group group = null;
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));
3003
3004                 groupBuilder.setGroupId(new GroupId(id));
3005                 groupBuilder.setGroupName(groupName);
3006                 groupBuilder.setGroupType(GroupTypes.GroupAll);
3007                 groupBuilder.setKey(key);
3008                 group = getGroup(groupBuilder, nodeBuilder);
3009                 break;
3010             }
3011         }
3012
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()) {
3019                 int index = 0;
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;
3030                             break;
3031                         }
3032                     }
3033                 }
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());
3041                             ab.setOrder(i);
3042                             ab.setKey(new ActionKey(i));
3043                             Action actionNewOrder = ab.build();
3044                             bucketActions.remove(action);
3045                             bucketActions.add(i, actionNewOrder);
3046                         }
3047                     }
3048
3049                 } else if (bucketActions.isEmpty()) {
3050                     /* remove bucket with empty action list */
3051                     buckets.getBucket().remove(bucket);
3052                     break;
3053                 }
3054             }
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);
3068
3069                 writeGroup(groupBuilder, nodeBuilder);
3070                 ApplyActionsBuilder aab = new ApplyActionsBuilder();
3071                 aab.setAction(actionList);
3072                 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3073                 return false;
3074             } else {
3075                 /* remove group with empty bucket. return true to delete flow */
3076                 removeGroup(groupBuilder, nodeBuilder);
3077                 return true;
3078             }
3079         } else {
3080             /* no group for port list. flow can be removed */
3081             return true;
3082         }
3083     }
3084
3085     @Override
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);
3098             }
3099             if (openflowID.contains(brIntDpid.toString())) {
3100                 this.initializeFlowRules(ovsNode, configurationService.getIntegrationBridgeName());
3101                 this.triggerInterfaceUpdates(ovsNode);
3102             }
3103         }
3104     }
3105
3106     private NodeBuilder createNodeBuilder(String nodeId) {
3107         NodeBuilder builder = new NodeBuilder();
3108         builder.setId(new NodeId(nodeId));
3109         builder.setKey(new NodeKey(builder.getId()));
3110         return builder;
3111     }
3112
3113     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder
3114                                                                                                                                              node) {
3115         return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
3116                 node.getKey()).toInstance();
3117     }
3118
3119     private String getInternalBridgeUUID (Node node, String bridgeName) {
3120         Preconditions.checkNotNull(ovsdbConfigurationService);
3121         try {
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;
3127             }
3128         } catch (Exception e) {
3129             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
3130         }
3131         return null;
3132     }
3133 }