Use Felix DM for OVSDB Neutron Services
[ovsdb.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / provider / 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.neutron.provider;
11
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Future;
20
21 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
22 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
23 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
24 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
25 import org.opendaylight.controller.sal.core.Node;
26 import org.opendaylight.controller.sal.utils.HexEncode;
27 import org.opendaylight.controller.sal.utils.ServiceHelper;
28 import org.opendaylight.controller.sal.utils.Status;
29 import org.opendaylight.controller.sal.utils.StatusCode;
30 import org.opendaylight.controller.switchmanager.ISwitchManager;
31 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
32 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
33 import org.opendaylight.ovsdb.lib.notation.UUID;
34 import org.opendaylight.ovsdb.lib.table.Bridge;
35 import org.opendaylight.ovsdb.lib.table.Interface;
36 import org.opendaylight.ovsdb.lib.table.Port;
37 import org.opendaylight.ovsdb.neutron.IAdminConfigManager;
38 import org.opendaylight.ovsdb.neutron.IInternalNetworkManager;
39 import org.opendaylight.ovsdb.neutron.IMDSALConsumer;
40 import org.opendaylight.ovsdb.neutron.NetworkHandler;
41 import org.opendaylight.ovsdb.neutron.ITenantNetworkManager;
42 import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
43 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
44 import org.opendaylight.ovsdb.plugin.StatusWithUuid;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.StripVlanActionCaseBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.strip.vlan.action._case.StripVlanAction;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.strip.vlan.action._case.StripVlanActionBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
113 import org.opendaylight.yangtools.yang.binding.DataObject;
114 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
115 import org.opendaylight.yangtools.yang.common.RpcResult;
116 import org.slf4j.Logger;
117 import org.slf4j.LoggerFactory;
118
119
120 /**
121  *
122  */
123 public class OF13Provider implements NetworkProvider {
124     private static final Logger logger = LoggerFactory.getLogger(OF13Provider.class);
125     private DataBrokerService dataBrokerService;
126     private static final short TABLE_0_DEFAULT_INGRESS = 0;
127     private static final short TABLE_1_ISOLATE_TENANT = 10;
128     private static final short TABLE_2_LOCAL_FORWARD = 20;
129
130     private IAdminConfigManager adminConfigManager;
131     private IInternalNetworkManager internalNetworkManager;
132     private ITenantNetworkManager tenantNetworkManager;
133
134     public OF13Provider(IAdminConfigManager adminConfigManager,
135                         IInternalNetworkManager internalNetworkManager,
136                         ITenantNetworkManager tenantNetworkManager) {
137         this.adminConfigManager = adminConfigManager;
138         this.internalNetworkManager = internalNetworkManager;
139         this.tenantNetworkManager = tenantNetworkManager;
140     }
141
142     @Override
143     public boolean hasPerTenantTunneling() {
144         return false;
145     }
146
147     private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
148         InetAddress srcTunnelEndPoint = adminConfigManager.getTunnelEndPoint(node);
149         if (srcTunnelEndPoint == null) {
150             logger.error("Tunnel Endpoint not configured for Node {}", node);
151             return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
152         }
153
154         if (!internalNetworkManager.isInternalNetworkNeutronReady(node)) {
155             logger.error(node+" is not Overlay ready");
156             return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
157         }
158
159         if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
160             logger.debug(node+" has no VM corresponding to segment "+ tunnelKey);
161             return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey);
162         }
163         return new Status(StatusCode.SUCCESS);
164     }
165
166     private String getTunnelName(String tunnelType, InetAddress dst) {
167         return tunnelType+"-"+dst.getHostAddress();
168     }
169
170     private boolean isTunnelPresent(Node node, String tunnelName, String bridgeUUID) throws Exception {
171         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
172         Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
173         if (bridge != null) {
174             Set<UUID> ports = bridge.getPorts();
175             for (UUID portUUID : ports) {
176                 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
177                 if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return true;
178             }
179         }
180         return false;
181     }
182
183     private String getPortUuid(Node node, String name, String bridgeUUID) throws Exception {
184         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
185         Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
186         if (bridge != null) {
187             Set<UUID> ports = bridge.getPorts();
188             for (UUID portUUID : ports) {
189                 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
190                 if (port != null && port.getName().equalsIgnoreCase(name)) return portUUID.toString();
191             }
192         }
193         return null;
194     }
195
196     private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
197         try {
198             String bridgeUUID = null;
199             String tunnelBridgeName = adminConfigManager.getIntegrationBridgeName();
200             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
201             Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
202             if (bridgeTable != null) {
203                 for (String uuid : bridgeTable.keySet()) {
204                     Bridge bridge = (Bridge)bridgeTable.get(uuid);
205                     if (bridge.getName().equals(tunnelBridgeName)) {
206                         bridgeUUID = uuid;
207                         break;
208                     }
209                 }
210             }
211             if (bridgeUUID == null) {
212                 logger.error("Could not find Bridge {} in {}", tunnelBridgeName, node);
213                 return new Status(StatusCode.NOTFOUND, "Could not find "+tunnelBridgeName+" in "+node);
214             }
215             String portName = getTunnelName(tunnelType, dst);
216
217             if (this.isTunnelPresent(node, portName, bridgeUUID)) {
218                 logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node);
219                 return new Status(StatusCode.SUCCESS);
220             }
221
222             Port tunnelPort = new Port();
223             tunnelPort.setName(portName);
224             StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, tunnelPort);
225             if (!statusWithUuid.isSuccess()) {
226                 logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID);
227                 return statusWithUuid;
228             }
229
230             String tunnelPortUUID = statusWithUuid.getUuid().toString();
231             String interfaceUUID = null;
232             int timeout = 6;
233             while ((interfaceUUID == null) && (timeout > 0)) {
234                 tunnelPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), tunnelPortUUID);
235                 OvsDBSet<UUID> interfaces = tunnelPort.getInterfaces();
236                 if (interfaces == null || interfaces.size() == 0) {
237                     // Wait for the OVSDB update to sync up the Local cache.
238                     Thread.sleep(500);
239                     timeout--;
240                     continue;
241                 }
242                 interfaceUUID = interfaces.toArray()[0].toString();
243                 Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), interfaceUUID);
244                 if (intf == null) interfaceUUID = null;
245             }
246
247             if (interfaceUUID == null) {
248                 logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID);
249                 return new Status(StatusCode.INTERNALERROR);
250             }
251
252             Interface tunInterface = new Interface();
253             tunInterface.setType(tunnelType);
254             OvsDBMap<String, String> options = new OvsDBMap<String, String>();
255             options.put("key", "flow");
256             options.put("local_ip", src.getHostAddress());
257             options.put("remote_ip", dst.getHostAddress());
258             tunInterface.setOptions(options);
259             Status status = ovsdbTable.updateRow(node, Interface.NAME.getName(), tunnelPortUUID, interfaceUUID, tunInterface);
260             logger.debug("Tunnel {} add status : {}", tunInterface, status);
261             return status;
262         } catch (Exception e) {
263             logger.error("Exception in addTunnelPort", e);
264             return new Status(StatusCode.INTERNALERROR);
265         }
266     }
267
268     /* delete port from ovsdb port table */
269     private Status deletePort(Node node, String bridgeName, String portName) {
270         try {
271             String bridgeUUID = null;
272             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
273             Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
274             if (bridgeTable != null) {
275                 for (String uuid : bridgeTable.keySet()) {
276                     Bridge bridge = (Bridge)bridgeTable.get(uuid);
277                     if (bridge.getName().equals(bridgeName)) {
278                         bridgeUUID = uuid;
279                         break;
280                     }
281                 }
282             }
283             if (bridgeUUID == null) {
284                 logger.debug("Could not find Bridge {} in {}", bridgeName, node);
285                 return new Status(StatusCode.SUCCESS);
286             }
287
288             String portUUID = this.getPortUuid(node, portName, bridgeUUID);
289             Status status = new Status(StatusCode.SUCCESS);
290             if (portUUID != null) {
291                status = ovsdbTable.deleteRow(node, Port.NAME.getName(), portUUID);
292                if (!status.isSuccess()) {
293                    logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID,
294                                 status);
295                    return status;
296                }
297                logger.debug("Port {} delete status : {}", portName, status);
298             }
299             return status;
300         } catch (Exception e) {
301             logger.error("Exception in deletePort", e);
302             return new Status(StatusCode.INTERNALERROR);
303         }
304     }
305
306     private Status deleteTunnelPort(Node node, String tunnelType, InetAddress src, InetAddress dst) {
307         String tunnelBridgeName = adminConfigManager.getIntegrationBridgeName();
308         String portName = getTunnelName(tunnelType, dst);
309         Status status = deletePort(node, tunnelBridgeName, portName);
310         return status;
311     }
312
313     private void programLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
314          /*
315          * Table(0) Rule #3
316          * ----------------
317          * Match: VM sMac and Local Ingress Port
318          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
319          */
320
321          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, true);
322
323         /*
324          * Table(0) Rule #4
325          * ----------------
326          * Match: Drop any remaining Ingress Local VM Packets
327          * Action: Drop w/ a low priority
328          */
329
330          handleDropSrcIface(dpid, localPort, true);
331
332          /*
333           * Table(2) Rule #1
334           * ----------------
335           * Match: Match TunID and Destination DL/dMAC Addr
336           * Action: Output Port
337           * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
338           */
339
340          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, true);
341
342          /*
343           * Table(2) Rule #2
344           * ----------------
345           * Match: Tunnel ID and dMAC (::::FF:FF)
346           * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
347           * actions=output:2,3,4,5
348           */
349
350           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
351
352           /*
353            * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
354            */
355           /*
356            * Table(1) Rule #3
357            * ----------------
358            * Match:  Any remaining Ingress Local VM Packets
359            * Action: Drop w/ a low priority
360            * -------------------------------------------
361            * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
362            */
363
364            handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, true);
365
366           /*
367            * Table(2) Rule #3
368            * ----------------
369            * Match: Any Remaining Flows w/a TunID
370            * Action: Drop w/ a low priority
371            * table=2,priority=8192,tun_id=0x5 actions=drop
372            */
373
374            handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, true);
375     }
376
377     private void removeLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
378         /*
379          ** Table(0) Rule #3
380          ** ----------------
381          ** Match: VM sMac and Local Ingress Port
382          ** Action:Action: Set Tunnel ID and GOTO Local Table (5)
383          **/
384
385         handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, false);
386
387         /*
388          ** Table(0) Rule #4
389          ** ----------------
390          ** Match: Drop any remaining Ingress Local VM Packets
391          ** Action: Drop w/ a low priority
392          **/
393
394         handleDropSrcIface(dpid, localPort, false);
395
396         /*
397          ** Table(2) Rule #1
398          ** ----------------
399          ** Match: Match TunID and Destination DL/dMAC Addr
400          ** Action: Output Port
401          ** table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
402          **/
403
404         handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, false);
405
406         /*
407          ** Table(2) Rule #2
408          ** ----------------
409          ** Match: Tunnel ID and dMAC (::::FF:FF)
410          ** table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
411          ** actions=output:2,3,4,5
412          **/
413
414         handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
415     }
416
417     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
418         /*
419          * Table(0) Rule #2
420          * ----------------
421          * Match: Ingress Port, Tunnel ID
422          * Action: GOTO Local Table (20)
423          */
424
425          handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
426
427          /*
428           * Table(1) Rule #2
429           * ----------------
430           * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
431           * Action: Flood to selected destination TEPs
432           * -------------------------------------------
433           * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
434           * actions=output:10,output:11,goto_table:2
435           */
436
437          handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
438
439     }
440
441     private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
442         /*
443          * Table(1) Rule #1
444          * ----------------
445          * Match: Drop any remaining Ingress Local VM Packets
446          * Action: Drop w/ a low priority
447          * -------------------------------------------
448          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
449          * actions=output:11,goto_table:2
450          */
451
452         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, true);
453     }
454
455     private void removeRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
456         /*
457          ** Table(1) Rule #1
458          ** ----------------
459          ** Match: Drop any remaining Ingress Local VM Packets
460          ** Action: Drop w/ a low priority
461          ** -------------------------------------------
462          ** table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
463          ** actions=output:11,goto_table:2
464          **/
465
466        handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, false);
467     }
468
469     /* Remove tunnel rules if last node in this tenant network */
470     private void removePerTunnelRules(Node node, Long dpid, String segmentationId, long tunnelOFPort) {
471         /*
472          ** TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
473          **/
474         /*
475          ** Table(1) Rule #3
476          ** ----------------
477          ** Match: Any remaining Ingress Local VM Packets
478          ** Action: Drop w/ a low priority
479          ** -------------------------------------------
480          ** table=1,priority=8192,tun_id=0x5 actions=goto_table:2
481          **/
482
483         handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, false);
484
485         /*
486          ** Table(2) Rule #3
487          ** ----------------
488          ** Match: Any Remaining Flows w/a TunID
489          ** Action: Drop w/ a low priority
490          ** table=2,priority=8192,tun_id=0x5 actions=drop
491          **/
492
493         handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
494
495        /*
496         ** Table(0) Rule #2
497         ** ----------------
498         ** Match: Ingress Port, Tunnel ID
499         ** Action: GOTO Local Table (10)
500         **/
501
502        handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
503
504        /*
505         ** Table(1) Rule #2
506         ** ----------------
507         ** Match: Match Tunnel ID and L2 ::::FF:FF Flooding
508         ** Action: Flood to selected destination TEPs
509         ** -------------------------------------------
510         ** table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
511         ** actions=output:10,output:11,goto_table:2
512         **/
513
514        handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
515     }
516
517     private Long getIntegrationBridgeOFDPID (Node node) {
518         try {
519             String bridgeName = adminConfigManager.getIntegrationBridgeName();
520             String brIntId = this.getInternalBridgeUUID(node, bridgeName);
521             if (brIntId == null) {
522                 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
523                 return 0L;
524             }
525
526             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
527             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
528             Set<String> dpids = bridge.getDatapath_id();
529             if (dpids == null || dpids.size() == 0) return 0L;
530             return Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0]));
531         } catch (Exception e) {
532             logger.error("Error finding Integration Bridge's OF DPID", e);
533             return 0L;
534         }
535     }
536     private void programLocalRules (String tunnelType, String segmentationId, Node node, Interface intf) {
537         try {
538             Long dpid = this.getIntegrationBridgeOFDPID(node);
539             if (dpid == 0L) {
540                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
541                 return;
542             }
543
544             Set<BigInteger> of_ports = intf.getOfport();
545             if (of_ports == null || of_ports.size() <= 0) {
546                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
547                 return;
548             }
549             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
550
551             Map<String, String> externalIds = intf.getExternal_ids();
552             if (externalIds == null) {
553                 logger.error("No external_ids seen in {}", intf);
554                 return;
555             }
556
557             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
558             if (attachedMac == null) {
559                 logger.error("No AttachedMac seen in {}", intf);
560                 return;
561             }
562
563             programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
564         } catch (Exception e) {
565             logger.error("Exception in programming Local Rules for "+intf+" on "+node, e);
566         }
567     }
568
569     private void removeLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
570         try {
571             Long dpid = this.getIntegrationBridgeOFDPID(node);
572             if (dpid == 0L) {
573                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
574                 return;
575             }
576
577             Set<BigInteger> of_ports = intf.getOfport();
578             if (of_ports == null || of_ports.size() <= 0) {
579                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
580                 return;
581             }
582             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
583
584             Map<String, String> externalIds = intf.getExternal_ids();
585             if (externalIds == null) {
586                 logger.error("No external_ids seen in {}", intf);
587                 return;
588             }
589
590             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
591             if (attachedMac == null) {
592                 logger.error("No AttachedMac seen in {}", intf);
593                 return;
594             }
595
596             /* Program local rules based on network type */
597             if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
598               networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
599                 logger.debug("Remove local bridge rules for interface {}", intf.getName());
600                 removeLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
601             }
602         } catch (Exception e) {
603             logger.error("Exception in removing Local Rules for "+intf+" on "+node, e);
604         }
605     }
606
607
608     private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
609             Interface intf, boolean local) {
610         try {
611
612             Long dpid = this.getIntegrationBridgeOFDPID(node);
613             if (dpid == 0L) {
614                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
615                 return;
616             }
617             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
618
619             Set<BigInteger> of_ports = intf.getOfport();
620             if (of_ports == null || of_ports.size() <= 0) {
621                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
622                 return;
623             }
624             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
625
626             Map<String, String> externalIds = intf.getExternal_ids();
627             if (externalIds == null) {
628                 logger.error("No external_ids seen in {}", intf);
629                 return;
630             }
631
632             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
633             if (attachedMac == null) {
634                 logger.error("No AttachedMac seen in {}", intf);
635                 return;
636             }
637
638             Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
639             if (intfs != null) {
640                 for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
641                     Interface tunIntf = (Interface)row;
642                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
643                         of_ports = tunIntf.getOfport();
644                         if (of_ports == null || of_ports.size() <= 0) {
645                             logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
646                             continue;
647                         }
648                         long tunnelOFPort = ((BigInteger)of_ports.toArray()[0]).longValue();
649
650                         if (tunnelOFPort == -1) {
651                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
652                             return;
653                         }
654                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
655
656                         if (!local) {
657                             programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
658                         }
659                         logger.trace("program local ingress tunnel rules: node" + node.getNodeIDString() + " intf " + intf.getName());
660                         if (local) {
661                             programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
662                         }
663                         return;
664                     }
665                 }
666             }
667         } catch (Exception e) {
668             logger.error("", e);
669         }
670     }
671
672     private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
673             Interface intf, boolean local, boolean isLastInstanceOnNode) {
674         try {
675
676             Long dpid = this.getIntegrationBridgeOFDPID(node);
677             if (dpid == 0L) {
678                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
679                 return;
680             }
681             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
682
683             Set<BigInteger> of_ports = intf.getOfport();
684             if (of_ports == null || of_ports.size() <= 0) {
685                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
686                 return;
687             }
688             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
689
690             Map<String, String> externalIds = intf.getExternal_ids();
691             if (externalIds == null) {
692                 logger.error("No external_ids seen in {}", intf);
693                 return;
694             }
695
696             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
697             if (attachedMac == null) {
698                 logger.error("No AttachedMac seen in {}", intf);
699                 return;
700             }
701
702             Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
703             if (intfs != null) {
704                 for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
705                     Interface tunIntf = (Interface)row;
706                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
707                         of_ports = tunIntf.getOfport();
708                         if (of_ports == null || of_ports.size() <= 0) {
709                             logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
710                             continue;
711                         }
712                         long tunnelOFPort = ((BigInteger)of_ports.toArray()[0]).longValue();
713
714                         if (tunnelOFPort == -1) {
715                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
716                             return;
717                         }
718                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
719
720                         if (!local) {
721                             removeRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
722                         }
723                         if (local && isLastInstanceOnNode) {
724                             removePerTunnelRules(node, dpid, segmentationId, tunnelOFPort);
725                         }
726                         return;
727                     }
728                 }
729             }
730         } catch (Exception e) {
731             logger.error("", e);
732         }
733     }
734
735     @Override
736     public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) {
737         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, "default", this);
738         if (switchManager == null) {
739             logger.error("Unable to identify SwitchManager");
740         } else {
741             Long dpid = this.getIntegrationBridgeOFDPID(srcNode);
742             if (dpid == 0L) {
743                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", srcNode);
744                 return new Status(StatusCode.NOTFOUND);
745             }
746             Set<Node> ofNodes = switchManager.getNodes();
747             boolean ofNodeFound = false;
748             if (ofNodes != null) {
749                 for (Node ofNode : ofNodes) {
750                     if (ofNode.toString().contains(dpid+"")) {
751                         logger.debug("Identified the Openflow node via toString {}", ofNode);
752                         ofNodeFound = true;
753                         break;
754                     }
755                 }
756             } else {
757                 logger.error("Unable to find any Node from SwitchManager");
758             }
759             if (!ofNodeFound) {
760                 logger.error("Unable to find OF Node for {} with update {} on node {}", dpid, intf, srcNode);
761                 return new Status(StatusCode.NOTFOUND);
762             }
763         }
764
765         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
766         List<Node> nodes = connectionService.getNodes();
767         nodes.remove(srcNode);
768         this.programLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf);
769
770         for (Node dstNode : nodes) {
771             InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
772             InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
773             Status status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst);
774             if (status.isSuccess()) {
775                 this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
776             }
777             addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
778             if (status.isSuccess()) {
779                 this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
780             }
781         }
782
783         return new Status(StatusCode.SUCCESS);
784     }
785
786     private Status triggerInterfaceUpdates(Node node) {
787         try {
788             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
789             Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
790             if (intfs != null) {
791                 for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
792                     Interface intf = (Interface)row;
793                     NeutronNetwork network = tenantNetworkManager.getTenantNetworkForInterface(intf);
794                     logger.debug("Trigger Interface update for {}", intf);
795                     if (network != null) {
796                         this.handleInterfaceUpdate(network, node, intf);
797                     }
798                 }
799             }
800         } catch (Exception e) {
801             logger.error("Error Triggering the lost interface updates for "+ node, e);
802             return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage());
803         }
804         return new Status(StatusCode.SUCCESS);
805     }
806     @Override
807     public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
808         // TODO Auto-generated method stub
809         return null;
810     }
811
812     @Override
813     public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf,
814             boolean isLastInstanceOnNode) {
815         Status status = new Status(StatusCode.SUCCESS);
816         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
817         List<Node> nodes = connectionService.getNodes();
818         nodes.remove(srcNode);
819
820         logger.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
821         if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
822         /* Delete tunnel port */
823             try {
824                 OvsDBMap<String, String> options = intf.getOptions();
825                 InetAddress src = InetAddress.getByName(options.get("local_ip"));
826                 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
827                 status = deleteTunnelPort(srcNode, intf.getType(), src, dst);
828             } catch (Exception e) {
829                 logger.error(e.getMessage(), e);
830              }
831         } else {
832             /* delete all other interfaces */
833             this.removeLocalRules(tunnelType, network.getProviderSegmentationID(),
834                                   srcNode, intf);
835
836             if (tunnelType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
837                  || tunnelType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
838                 for (Node dstNode : nodes) {
839                     InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
840                     InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
841                     logger.info("Remove tunnel rules for interface " + intf.getName() + " on srcNode" + srcNode.getNodeIDString());
842                     this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
843                                            dst, srcNode, intf, true, isLastInstanceOnNode);
844                     logger.info("Remove tunnel rules for interface " + intf.getName() + " on dstNode" + dstNode.getNodeIDString());
845                     this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
846                                            src, dstNode, intf, false, isLastInstanceOnNode);
847                 }
848             }
849         }
850         return status;
851     }
852
853     @Override
854     public void initializeFlowRules(Node node) {
855         this.initializeFlowRules(node, adminConfigManager.getIntegrationBridgeName());
856         this.triggerInterfaceUpdates(node);
857     }
858
859     /**
860      * @param node
861      * @param bridgeName
862      */
863     private void initializeFlowRules(Node node, String bridgeName) {
864         Long dpid = this.getIntegrationBridgeOFDPID(node);
865         if (dpid == 0L) {
866             logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
867             return;
868         }
869
870         /*
871          * Table(0) Rule #1
872          * ----------------
873          * Match: LLDP (0x88CCL)
874          * Action: Packet_In to Controller Reserved Port
875          */
876
877          writeLLDPRule(dpid);
878     }
879
880     /*
881     * Create an LLDP Flow Rule to encapsulate into
882     * a packet_in that is sent to the controller
883     * for topology handling.
884     * Match: Ethertype 0x88CCL
885     * Action: Punt to Controller in a Packet_In msg
886     */
887
888     private void writeLLDPRule(Long dpidLong) {
889
890         String nodeName = "openflow:" + dpidLong;
891         EtherType etherType = new EtherType(0x88CCL);
892
893         MatchBuilder matchBuilder = new MatchBuilder();
894         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
895         FlowBuilder flowBuilder = new FlowBuilder();
896
897         // Create Match(es) and Set them in the FlowBuilder Object
898         flowBuilder.setMatch(createEtherTypeMatch(matchBuilder, etherType).build());
899
900         // Create the OF Actions and Instructions
901         InstructionBuilder ib = new InstructionBuilder();
902         InstructionsBuilder isb = new InstructionsBuilder();
903
904         // Instructions List Stores Individual Instructions
905         List<Instruction> instructions = new ArrayList<Instruction>();
906
907         // Call the InstructionBuilder Methods Containing Actions
908         createSendToControllerInstructions(ib);
909         ib.setOrder(0);
910         ib.setKey(new InstructionKey(0));
911         instructions.add(ib.build());
912
913         // Add InstructionBuilder to the Instruction(s)Builder List
914         isb.setInstruction(instructions);
915
916         // Add InstructionsBuilder to FlowBuilder
917         flowBuilder.setInstructions(isb.build());
918
919         String flowId = "LLDP";
920         flowBuilder.setId(new FlowId(flowId));
921         FlowKey key = new FlowKey(new FlowId(flowId));
922         flowBuilder.setBarrier(true);
923         flowBuilder.setTableId((short) 0);
924         flowBuilder.setKey(key);
925         flowBuilder.setFlowName(flowId);
926         flowBuilder.setHardTimeout(0);
927         flowBuilder.setIdleTimeout(0);
928         writeFlow(flowBuilder, nodeBuilder);
929     }
930
931     /*
932      * (Table:0) Ingress Tunnel Traffic
933      * Match: OpenFlow InPort and Tunnel ID
934      * Action: GOTO Local Table (10)
935      * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
936      */
937
938     private void handleTunnelIn(Long dpidLong, Short writeTable, Short goToTableId,
939                                 String segmentationId,  Long ofPort, boolean write) {
940
941         String nodeName = "openflow:" + dpidLong;
942
943         BigInteger tunnelId = new BigInteger(segmentationId);
944         MatchBuilder matchBuilder = new MatchBuilder();
945         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
946         FlowBuilder flowBuilder = new FlowBuilder();
947
948         // Create Match(es) and Set them in the FlowBuilder Object
949         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, tunnelId).build());
950         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, ofPort).build());
951
952         if (write) {
953             // Create the OF Actions and Instructions
954             InstructionBuilder ib = new InstructionBuilder();
955             InstructionsBuilder isb = new InstructionsBuilder();
956
957             // Instructions List Stores Individual Instructions
958             List<Instruction> instructions = new ArrayList<Instruction>();
959
960             // Call the InstructionBuilder Methods Containing Actions
961             createGotoTableInstructions(ib, goToTableId);
962             ib.setOrder(0);
963             ib.setKey(new InstructionKey(0));
964             instructions.add(ib.build());
965
966             // Add InstructionBuilder to the Instruction(s)Builder List
967             isb.setInstruction(instructions);
968
969             // Add InstructionsBuilder to FlowBuilder
970             flowBuilder.setInstructions(isb.build());
971         }
972
973         String flowId = "TunnelIn_"+segmentationId+"_"+ofPort;
974         // Add Flow Attributes
975         flowBuilder.setId(new FlowId(flowId));
976         FlowKey key = new FlowKey(new FlowId(flowId));
977         flowBuilder.setStrict(true);
978         flowBuilder.setBarrier(false);
979         flowBuilder.setTableId(writeTable);
980         flowBuilder.setKey(key);
981         flowBuilder.setFlowName(flowId);
982         flowBuilder.setHardTimeout(0);
983         flowBuilder.setIdleTimeout(0);
984
985         if (write) {
986             writeFlow(flowBuilder, nodeBuilder);
987         } else {
988             removeFlow(flowBuilder, nodeBuilder);
989         }
990     }
991
992    /*
993     * (Table:0) Egress VM Traffic Towards TEP
994     * Match: Destination Ethernet Addr and OpenFlow InPort
995     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
996     * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
997     * actions=set_field:5->tun_id,goto_table=1"
998     */
999
1000     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
1001                                    String segmentationId, Long inPort, String attachedMac, boolean write) {
1002
1003         String nodeName = "openflow:" + dpidLong;
1004
1005         MatchBuilder matchBuilder = new MatchBuilder();
1006         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1007         FlowBuilder flowBuilder = new FlowBuilder();
1008
1009         // Create the OF Match using MatchBuilder
1010         flowBuilder.setMatch(createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
1011         // TODO Broken In_Port Match
1012         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
1013
1014         String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
1015         // Add Flow Attributes
1016         flowBuilder.setId(new FlowId(flowId));
1017         FlowKey key = new FlowKey(new FlowId(flowId));
1018         flowBuilder.setStrict(true);
1019         flowBuilder.setBarrier(false);
1020         flowBuilder.setTableId(writeTable);
1021         flowBuilder.setKey(key);
1022         flowBuilder.setFlowName(flowId);
1023         flowBuilder.setHardTimeout(0);
1024         flowBuilder.setIdleTimeout(0);
1025
1026         if (write) {
1027             // Instantiate the Builders for the OF Actions and Instructions
1028             InstructionBuilder ib = new InstructionBuilder();
1029             InstructionsBuilder isb = new InstructionsBuilder();
1030
1031             // Instructions List Stores Individual Instructions
1032             List<Instruction> instructions = new ArrayList<Instruction>();
1033
1034             // GOTO Instuctions Need to be added first to the List
1035             createGotoTableInstructions(ib, goToTableId);
1036             ib.setOrder(0);
1037             ib.setKey(new InstructionKey(0));
1038             instructions.add(ib.build());
1039             // TODO Broken SetTunID
1040             createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
1041             ib.setOrder(1);
1042             ib.setKey(new InstructionKey(1));
1043             instructions.add(ib.build());
1044
1045             // Add InstructionBuilder to the Instruction(s)Builder List
1046             isb.setInstruction(instructions);
1047
1048             // Add InstructionsBuilder to FlowBuilder
1049             flowBuilder.setInstructions(isb.build());
1050
1051             writeFlow(flowBuilder, nodeBuilder);
1052         } else {
1053             removeFlow(flowBuilder, nodeBuilder);
1054         }
1055     }
1056
1057     /*
1058      * (Table:0) Drop frames sourced from a VM that do not
1059      * match the associated MAC address of the local VM.
1060      * Match: Low priority anything not matching the VM SMAC
1061      * Instruction: Drop
1062      * table=0,priority=16384,in_port=1 actions=drop"
1063      */
1064
1065     private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
1066
1067         String nodeName = "openflow:" + dpidLong;
1068
1069         MatchBuilder matchBuilder = new MatchBuilder();
1070         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1071         FlowBuilder flowBuilder = new FlowBuilder();
1072
1073         // Create the OF Match using MatchBuilder
1074         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
1075
1076         if (write) {
1077             // Instantiate the Builders for the OF Actions and Instructions
1078             InstructionBuilder ib = new InstructionBuilder();
1079             InstructionsBuilder isb = new InstructionsBuilder();
1080
1081             // Instructions List Stores Individual Instructions
1082             List<Instruction> instructions = new ArrayList<Instruction>();
1083
1084             // Call the InstructionBuilder Methods Containing Actions
1085             createDropInstructions(ib);
1086             ib.setOrder(0);
1087             ib.setKey(new InstructionKey(0));
1088             instructions.add(ib.build());
1089
1090             // Add InstructionBuilder to the Instruction(s)Builder List
1091             isb.setInstruction(instructions);
1092
1093             // Add InstructionsBuilder to FlowBuilder
1094             flowBuilder.setInstructions(isb.build());
1095         }
1096
1097         String flowId = "DropFilter_"+inPort;
1098         // Add Flow Attributes
1099         flowBuilder.setId(new FlowId(flowId));
1100         FlowKey key = new FlowKey(new FlowId(flowId));
1101         flowBuilder.setStrict(true);
1102         flowBuilder.setBarrier(false);
1103         flowBuilder.setTableId((short) 0);
1104         flowBuilder.setKey(key);
1105         flowBuilder.setFlowName(flowId);
1106         flowBuilder.setPriority(8192);
1107         flowBuilder.setHardTimeout(0);
1108         flowBuilder.setIdleTimeout(0);
1109         if (write) {
1110             writeFlow(flowBuilder, nodeBuilder);
1111         } else {
1112             removeFlow(flowBuilder, nodeBuilder);
1113         }
1114     }
1115
1116    /*
1117     * (Table:1) Egress Tunnel Traffic
1118     * Match: Destination Ethernet Addr and Local InPort
1119     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1120     * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
1121     * actions=output:10,goto_table:2"
1122     */
1123
1124     private void handleTunnelOut(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId,
1125                                  Long OFPortOut, String attachedMac, boolean write) {
1126
1127         String nodeName = "openflow:" + dpidLong;
1128
1129         MatchBuilder matchBuilder = new MatchBuilder();
1130         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1131         FlowBuilder flowBuilder = new FlowBuilder();
1132
1133         // Create the OF Match using MatchBuilder
1134         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1135         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
1136
1137         String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
1138         // Add Flow Attributes
1139         flowBuilder.setId(new FlowId(flowId));
1140         FlowKey key = new FlowKey(new FlowId(flowId));
1141         flowBuilder.setStrict(true);
1142         flowBuilder.setBarrier(false);
1143         flowBuilder.setTableId(writeTable);
1144         flowBuilder.setKey(key);
1145         flowBuilder.setFlowName(flowId);
1146         flowBuilder.setHardTimeout(0);
1147         flowBuilder.setIdleTimeout(0);
1148
1149         if (write) {
1150             // Instantiate the Builders for the OF Actions and Instructions
1151             InstructionBuilder ib = new InstructionBuilder();
1152             InstructionsBuilder isb = new InstructionsBuilder();
1153
1154             // Instructions List Stores Individual Instructions
1155             List<Instruction> instructions = new ArrayList<Instruction>();
1156
1157             // GOTO Instuctions
1158             createGotoTableInstructions(ib, goToTableId);
1159             ib.setOrder(0);
1160             ib.setKey(new InstructionKey(0));
1161             instructions.add(ib.build());
1162             // Set the Output Port/Iface
1163             createOutputPortInstructions(ib, dpidLong, OFPortOut);
1164             ib.setOrder(1);
1165             ib.setKey(new InstructionKey(1));
1166             instructions.add(ib.build());
1167
1168             // Add InstructionBuilder to the Instruction(s)Builder List
1169             isb.setInstruction(instructions);
1170
1171             // Add InstructionsBuilder to FlowBuilder
1172             flowBuilder.setInstructions(isb.build());
1173
1174             writeFlow(flowBuilder, nodeBuilder);
1175         } else {
1176             removeFlow(flowBuilder, nodeBuilder);
1177         }
1178     }
1179
1180        /*
1181     * (Table:1) Egress Tunnel Traffic
1182     * Match: Destination Ethernet Addr and Local InPort
1183     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1184     * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1185     * actions=output:10,output:11,goto_table:2
1186     */
1187
1188     private void handleTunnelFloodOut(Long dpidLong, Short writeTable, Short localTable,
1189                                       String segmentationId,  Long OFPortOut, boolean write) {
1190
1191         String nodeName = "openflow:" + dpidLong;
1192
1193         MatchBuilder matchBuilder = new MatchBuilder();
1194         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1195         FlowBuilder flowBuilder = new FlowBuilder();
1196
1197         // Create the OF Match using MatchBuilder
1198         // Match TunnelID
1199         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1200         // Match DMAC
1201
1202         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
1203
1204         String flowId = "TunnelFloodOut_"+segmentationId;
1205         // Add Flow Attributes
1206         flowBuilder.setId(new FlowId(flowId));
1207         FlowKey key = new FlowKey(new FlowId(flowId));
1208         flowBuilder.setBarrier(true);
1209         flowBuilder.setTableId(writeTable);
1210         flowBuilder.setKey(key);
1211         flowBuilder.setPriority(16384);
1212         flowBuilder.setFlowName(flowId);
1213         flowBuilder.setHardTimeout(0);
1214         flowBuilder.setIdleTimeout(0);
1215
1216         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
1217         // Instantiate the Builders for the OF Actions and Instructions
1218         InstructionBuilder ib = new InstructionBuilder();
1219         InstructionsBuilder isb = new InstructionsBuilder();
1220         List<Instruction> instructions = new ArrayList<Instruction>();
1221         List<Instruction> existingInstructions = null;
1222         if (flow != null) {
1223             Instructions ins = flow.getInstructions();
1224             if (ins != null) {
1225                 existingInstructions = ins.getInstruction();
1226             }
1227         }
1228
1229         if (write) {
1230             // GOTO Instuction
1231             createGotoTableInstructions(ib, localTable);
1232             ib.setOrder(0);
1233             ib.setKey(new InstructionKey(0));
1234             instructions.add(ib.build());
1235             // Set the Output Port/Iface
1236             createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
1237             ib.setOrder(1);
1238             ib.setKey(new InstructionKey(1));
1239             instructions.add(ib.build());
1240
1241             // Add InstructionBuilder to the Instruction(s)Builder List
1242             isb.setInstruction(instructions);
1243
1244             // Add InstructionsBuilder to FlowBuilder
1245             flowBuilder.setInstructions(isb.build());
1246
1247             writeFlow(flowBuilder, nodeBuilder);
1248         } else {
1249             /* remove port from action list */
1250             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,OFPortOut, existingInstructions);
1251             if (flowRemove) {
1252                 /* if all port are removed, remove the flow too. */
1253                 removeFlow(flowBuilder, nodeBuilder);
1254             } else {
1255                 /* Install instruction with new output port list*/
1256                 ib.setOrder(0);
1257                 ib.setKey(new InstructionKey(0));
1258                 instructions.add(ib.build());
1259
1260                 // Add InstructionBuilder to the Instruction(s)Builder List
1261                 isb.setInstruction(instructions);
1262
1263                 // Add InstructionsBuilder to FlowBuilder
1264                 flowBuilder.setInstructions(isb.build());
1265             }
1266         }
1267     }
1268
1269    /*
1270     * (Table:1) Table Drain w/ Catch All
1271     * Match: Tunnel ID
1272     * Action: GOTO Local Table (10)
1273     * table=2,priority=8192,tun_id=0x5 actions=drop
1274     */
1275
1276     private void handleTunnelMiss(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId, boolean write) {
1277
1278         String nodeName = "openflow:" + dpidLong;
1279
1280         MatchBuilder matchBuilder = new MatchBuilder();
1281         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1282         FlowBuilder flowBuilder = new FlowBuilder();
1283
1284         // Create Match(es) and Set them in the FlowBuilder Object
1285         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1286
1287         if (write) {
1288             // Create the OF Actions and Instructions
1289             InstructionBuilder ib = new InstructionBuilder();
1290             InstructionsBuilder isb = new InstructionsBuilder();
1291
1292             // Instructions List Stores Individual Instructions
1293             List<Instruction> instructions = new ArrayList<Instruction>();
1294
1295             // Call the InstructionBuilder Methods Containing Actions
1296             createGotoTableInstructions(ib, goToTableId);
1297             ib.setOrder(0);
1298             ib.setKey(new InstructionKey(0));
1299             instructions.add(ib.build());
1300
1301             // Add InstructionBuilder to the Instruction(s)Builder List
1302             isb.setInstruction(instructions);
1303
1304             // Add InstructionsBuilder to FlowBuilder
1305             flowBuilder.setInstructions(isb.build());
1306         }
1307
1308         String flowId = "TunnelMiss_"+segmentationId;
1309         // Add Flow Attributes
1310         flowBuilder.setId(new FlowId(flowId));
1311         FlowKey key = new FlowKey(new FlowId(flowId));
1312         flowBuilder.setStrict(true);
1313         flowBuilder.setBarrier(false);
1314         flowBuilder.setTableId(writeTable);
1315         flowBuilder.setKey(key);
1316         flowBuilder.setPriority(8192);
1317         flowBuilder.setFlowName(flowId);
1318         flowBuilder.setHardTimeout(0);
1319         flowBuilder.setIdleTimeout(0);
1320         if (write) {
1321             writeFlow(flowBuilder, nodeBuilder);
1322         } else {
1323             removeFlow(flowBuilder, nodeBuilder);
1324         }
1325     }
1326
1327     /*
1328      * (Table:1) Local Broadcast Flood
1329      * Match: Tunnel ID and dMAC
1330      * Action: Output Port
1331      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
1332      */
1333
1334     private void handleLocalUcastOut(Long dpidLong, Short writeTable, String segmentationId, Long localPort,
1335                                      String attachedMac, boolean write) {
1336
1337         String nodeName = "openflow:" + dpidLong;
1338
1339         MatchBuilder matchBuilder = new MatchBuilder();
1340         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1341         FlowBuilder flowBuilder = new FlowBuilder();
1342
1343         // Create the OF Match using MatchBuilder
1344         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1345         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
1346
1347         String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
1348         // Add Flow Attributes
1349         flowBuilder.setId(new FlowId(flowId));
1350         FlowKey key = new FlowKey(new FlowId(flowId));
1351         flowBuilder.setStrict(true);
1352         flowBuilder.setBarrier(false);
1353         flowBuilder.setTableId(writeTable);
1354         flowBuilder.setKey(key);
1355         flowBuilder.setFlowName(flowId);
1356         flowBuilder.setHardTimeout(0);
1357         flowBuilder.setIdleTimeout(0);
1358
1359         if (write) {
1360             // Instantiate the Builders for the OF Actions and Instructions
1361             InstructionBuilder ib = new InstructionBuilder();
1362             InstructionsBuilder isb = new InstructionsBuilder();
1363
1364             // Instructions List Stores Individual Instructions
1365             List<Instruction> instructions = new ArrayList<Instruction>();
1366
1367             // Set the Output Port/Iface
1368             createOutputPortInstructions(ib, dpidLong, localPort);
1369             ib.setOrder(0);
1370             ib.setKey(new InstructionKey(0));
1371             instructions.add(ib.build());
1372
1373             // Add InstructionBuilder to the Instruction(s)Builder List
1374             isb.setInstruction(instructions);
1375
1376             // Add InstructionsBuilder to FlowBuilder
1377             flowBuilder.setInstructions(isb.build());
1378             writeFlow(flowBuilder, nodeBuilder);
1379         } else {
1380             removeFlow(flowBuilder, nodeBuilder);
1381         }
1382     }
1383
1384     /*
1385      * (Table:1) Local Broadcast Flood
1386      * Match: Tunnel ID and dMAC (::::FF:FF)
1387      * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1388      * actions=output:2,3,4,5
1389      */
1390
1391     private void handleLocalBcastOut(Long dpidLong, Short writeTable, String segmentationId,
1392                                      Long localPort, boolean write) {
1393
1394         String nodeName = "openflow:" + dpidLong;
1395
1396         MatchBuilder matchBuilder = new MatchBuilder();
1397         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1398         FlowBuilder flowBuilder = new FlowBuilder();
1399
1400         // Create the OF Match using MatchBuilder
1401         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1402         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
1403
1404         String flowId = "BcastOut_"+segmentationId;
1405         // Add Flow Attributes
1406         flowBuilder.setId(new FlowId(flowId));
1407         FlowKey key = new FlowKey(new FlowId(flowId));
1408         flowBuilder.setStrict(true);
1409         flowBuilder.setBarrier(false);
1410         flowBuilder.setTableId(writeTable);
1411         flowBuilder.setKey(key);
1412         flowBuilder.setPriority(16384);
1413         flowBuilder.setFlowName(flowId);
1414         flowBuilder.setHardTimeout(0);
1415         flowBuilder.setIdleTimeout(0);
1416         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
1417         // Instantiate the Builders for the OF Actions and Instructions
1418         InstructionBuilder ib = new InstructionBuilder();
1419         InstructionsBuilder isb = new InstructionsBuilder();
1420         List<Instruction> instructions = new ArrayList<Instruction>();
1421         List<Instruction> existingInstructions = null;
1422         if (flow != null) {
1423             Instructions ins = flow.getInstructions();
1424             if (ins != null) {
1425                 existingInstructions = ins.getInstruction();
1426             }
1427         }
1428
1429         if (write) {
1430             // Create output port list
1431             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
1432             ib.setOrder(0);
1433             ib.setKey(new InstructionKey(0));
1434             instructions.add(ib.build());
1435
1436             // Add InstructionBuilder to the Instruction(s)Builder List
1437             isb.setInstruction(instructions);
1438
1439             // Add InstructionsBuilder to FlowBuilder
1440             flowBuilder.setInstructions(isb.build());
1441
1442             writeFlow(flowBuilder, nodeBuilder);
1443         } else {
1444             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
1445                                        localPort, existingInstructions);
1446             if (flowRemove) {
1447                    /* if all ports are removed, remove flow */
1448                  removeFlow(flowBuilder, nodeBuilder);
1449                } else {
1450                 /* Install instruction with new output port list*/
1451                    ib.setOrder(0);
1452                    ib.setKey(new InstructionKey(0));
1453                  instructions.add(ib.build());
1454
1455                 // Add InstructionBuilder to the Instruction(s)Builder List
1456                 isb.setInstruction(instructions);
1457
1458                 // Add InstructionsBuilder to FlowBuilder
1459                    flowBuilder.setInstructions(isb.build());
1460
1461                    writeFlow(flowBuilder, nodeBuilder);
1462             }
1463         }
1464     }
1465
1466     /*
1467      * (Table:1) Local Table Miss
1468      * Match: Any Remaining Flows w/a TunID
1469      * Action: Drop w/ a low priority
1470      * table=2,priority=8192,tun_id=0x5 actions=drop
1471      */
1472
1473     private void handleLocalTableMiss(Long dpidLong, Short writeTable, String segmentationId,
1474                                       boolean write) {
1475
1476         String nodeName = "openflow:" + dpidLong;
1477
1478         MatchBuilder matchBuilder = new MatchBuilder();
1479         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1480         FlowBuilder flowBuilder = new FlowBuilder();
1481
1482         // Create Match(es) and Set them in the FlowBuilder Object
1483         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1484
1485         if (write) {
1486             // Create the OF Actions and Instructions
1487             InstructionBuilder ib = new InstructionBuilder();
1488             InstructionsBuilder isb = new InstructionsBuilder();
1489
1490             // Instructions List Stores Individual Instructions
1491             List<Instruction> instructions = new ArrayList<Instruction>();
1492
1493             // Call the InstructionBuilder Methods Containing Actions
1494             createDropInstructions(ib);
1495             ib.setOrder(0);
1496             ib.setKey(new InstructionKey(0));
1497             instructions.add(ib.build());
1498
1499             // Add InstructionBuilder to the Instruction(s)Builder List
1500             isb.setInstruction(instructions);
1501
1502             // Add InstructionsBuilder to FlowBuilder
1503             flowBuilder.setInstructions(isb.build());
1504         }
1505
1506         String flowId = "LocalTableMiss_"+segmentationId;
1507         // Add Flow Attributes
1508         flowBuilder.setId(new FlowId(flowId));
1509         FlowKey key = new FlowKey(new FlowId(flowId));
1510         flowBuilder.setStrict(true);
1511         flowBuilder.setBarrier(false);
1512         flowBuilder.setTableId(writeTable);
1513         flowBuilder.setKey(key);
1514         flowBuilder.setPriority(8192);
1515         flowBuilder.setFlowName(flowId);
1516         flowBuilder.setHardTimeout(0);
1517         flowBuilder.setIdleTimeout(0);
1518         if (write) {
1519             writeFlow(flowBuilder, nodeBuilder);
1520         } else {
1521             removeFlow(flowBuilder, nodeBuilder);
1522         }
1523     }
1524
1525     private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
1526         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
1527         if (mdsalConsumer == null) {
1528             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
1529             return null;
1530         }
1531
1532         dataBrokerService = mdsalConsumer.getDataBrokerService();
1533
1534         if (dataBrokerService == null) {
1535             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
1536             return null;
1537         }
1538
1539         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1540                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
1541                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
1542         return (Flow)dataBrokerService.readConfigurationData(path1);
1543     }
1544
1545     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
1546         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
1547         if (mdsalConsumer == null) {
1548             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
1549             return;
1550         }
1551
1552         dataBrokerService = mdsalConsumer.getDataBrokerService();
1553
1554         if (dataBrokerService == null) {
1555             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
1556             return;
1557         }
1558         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
1559         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1560                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
1561                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
1562         modification.putOperationalData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
1563         modification.putOperationalData(path1, flowBuilder.build());
1564         modification.putConfigurationData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
1565         modification.putConfigurationData(path1, flowBuilder.build());
1566         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
1567         try {
1568             RpcResult<TransactionStatus> result = commitFuture.get();
1569             TransactionStatus status = result.getResult();
1570             logger.debug("Transaction Status "+status.toString()+" for Flow "+flowBuilder.getFlowName());
1571         } catch (InterruptedException e) {
1572             logger.error(e.getMessage(), e);
1573         } catch (ExecutionException e) {
1574             logger.error(e.getMessage(), e);
1575         }
1576     }
1577
1578     private void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
1579         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
1580         if (mdsalConsumer == null) {
1581             logger.error("ERROR finding MDSAL Service.");
1582             return;
1583         }
1584
1585         dataBrokerService = mdsalConsumer.getDataBrokerService();
1586
1587         if (dataBrokerService == null) {
1588             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SALsupport on the Controller.");
1589             return;
1590         }
1591         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
1592         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
1593                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1594                 .rev130819.nodes.Node.class, nodeBuilder.getKey())
1595                 .augmentation(FlowCapableNode.class).child(Table.class,
1596                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
1597         //modification.removeOperationalData(nodeBuilderToInstanceId(nodeBuilder));
1598         modification.removeOperationalData(path1);
1599         //modification.removeConfigurationData(nodeBuilderToInstanceId(nodeBuilder));
1600         modification.removeConfigurationData(path1);
1601         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
1602         try {
1603             RpcResult<TransactionStatus> result = commitFuture.get();
1604             TransactionStatus status = result.getResult();
1605             logger.debug("Transaction Status "+status.toString()+" for Flow "+flowBuilder.getFlowName());
1606         } catch (InterruptedException e) {
1607             logger.error(e.getMessage(), e);
1608         } catch (ExecutionException e) {
1609             logger.error(e.getMessage(), e);
1610         }
1611     }
1612
1613     /**
1614      * Create Ingress Port Match dpidLong, inPort
1615      *
1616      * @param matchBuilder  Map matchBuilder MatchBuilder Object without a match
1617      * @param dpidLong      Long the datapath ID of a switch/node
1618      * @param inPort        Long ingress port on a switch
1619      * @return matchBuilder Map MatchBuilder Object with a match
1620      */
1621     protected static MatchBuilder createInPortMatch(MatchBuilder matchBuilder, Long dpidLong, Long inPort) {
1622
1623         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + inPort);
1624         logger.debug("createInPortMatch() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, inPort);
1625         matchBuilder.setInPort(NodeConnectorId.getDefaultInstance(ncid.getValue()));
1626         matchBuilder.setInPort(ncid);
1627
1628         return matchBuilder;
1629     }
1630
1631     /**
1632      * Create EtherType Match
1633      *
1634      * @param matchBuilder  Map matchBuilder MatchBuilder Object without a match
1635      * @param etherType     Long EtherType
1636      * @return matchBuilder Map MatchBuilder Object with a match
1637      */
1638     protected static MatchBuilder createEtherTypeMatch(MatchBuilder matchBuilder, EtherType etherType) {
1639
1640         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
1641         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
1642         ethTypeBuilder.setType(new EtherType(etherType));
1643         ethernetMatch.setEthernetType(ethTypeBuilder.build());
1644         matchBuilder.setEthernetMatch(ethernetMatch.build());
1645
1646         return matchBuilder;
1647     }
1648
1649     /**
1650      * Create Ethernet Source Match
1651      *
1652      * @param matchBuilder  MatchBuilder Object without a match yet
1653      * @param sMacAddr      String representing a source MAC
1654      * @return matchBuilder Map MatchBuilder Object with a match
1655      */
1656     protected static MatchBuilder createEthSrcMatch(MatchBuilder matchBuilder, MacAddress sMacAddr) {
1657
1658         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
1659         EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder();
1660         ethSourceBuilder.setAddress(new MacAddress(sMacAddr));
1661         ethernetMatch.setEthernetSource(ethSourceBuilder.build());
1662         matchBuilder.setEthernetMatch(ethernetMatch.build());
1663
1664         return matchBuilder;
1665     }
1666
1667     /**
1668      * Create Ethernet Destination Match
1669      *
1670      * @param matchBuilder MatchBuilder Object without a match yet
1671      * @param vlanId       Integer representing a VLAN ID Integer representing a VLAN ID
1672      * @return matchBuilder Map MatchBuilder Object with a match
1673      */
1674
1675     protected static MatchBuilder createVlanIdMatch(MatchBuilder matchBuilder, VlanId vlanId) {
1676
1677         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
1678         VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
1679         vlanIdBuilder.setVlanId(new VlanId(vlanId));
1680         vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
1681         matchBuilder.setVlanMatch(vlanMatchBuilder.build());
1682
1683         return matchBuilder;
1684     }
1685
1686     /**
1687      * Create Ethernet Destination Match
1688      *
1689      * @param matchBuilder  MatchBuilder Object without a match yet
1690      * @param dMacAddr      String representing a destination MAC
1691      * @return matchBuilder Map MatchBuilder Object with a match
1692      */
1693
1694     protected static MatchBuilder createDestEthMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, MacAddress mask) {
1695
1696         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
1697         EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
1698         ethDestinationBuilder.setAddress(new MacAddress(dMacAddr));
1699         if (mask != null) {
1700             ethDestinationBuilder.setMask(mask);
1701         }
1702         ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
1703         matchBuilder.setEthernetMatch(ethernetMatch.build());
1704
1705         return matchBuilder;
1706     }
1707
1708     /**
1709      * Tunnel ID Match Builder
1710      *
1711      * @param matchBuilder  MatchBuilder Object without a match yet
1712      * @param tunnelId      BigInteger representing a tunnel ID
1713      * @return matchBuilder Map MatchBuilder Object with a match
1714      */
1715     protected static MatchBuilder createTunnelIDMatch(MatchBuilder matchBuilder, BigInteger tunnelId) {
1716
1717         TunnelBuilder tunnelBuilder = new TunnelBuilder();
1718         tunnelBuilder.setTunnelId(tunnelId);
1719         matchBuilder.setTunnel(tunnelBuilder.build());
1720
1721         return matchBuilder;
1722     }
1723
1724     /**
1725      * Match ICMP code and type
1726      *
1727      * @param matchBuilder  MatchBuilder Object without a match yet
1728      * @param type          short representing an ICMP type
1729      * @param code          short representing an ICMP code
1730      * @return matchBuilder Map MatchBuilder Object with a match
1731      */
1732     protected static MatchBuilder createICMPv4Match(MatchBuilder matchBuilder, short type, short code) {
1733
1734         EthernetMatchBuilder eth = new EthernetMatchBuilder();
1735         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
1736         ethTypeBuilder.setType(new EtherType(0x0800L));
1737         eth.setEthernetType(ethTypeBuilder.build());
1738         matchBuilder.setEthernetMatch(eth.build());
1739
1740         // Build the IPv4 Match requied per OVS Syntax
1741         IpMatchBuilder ipmatch = new IpMatchBuilder();
1742         ipmatch.setIpProtocol((short) 1);
1743         matchBuilder.setIpMatch(ipmatch.build());
1744
1745         // Build the ICMPv4 Match
1746         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
1747         icmpv4match.setIcmpv4Type(type);
1748         icmpv4match.setIcmpv4Code(code);
1749         matchBuilder.setIcmpv4Match(icmpv4match.build());
1750
1751         return matchBuilder;
1752     }
1753
1754     /**
1755      * @param matchBuilder MatchBuilder Object without a match yet
1756      * @param dstip        String containing an IPv4 prefix
1757      * @return matchBuilder Map Object with a match
1758      */
1759     private static MatchBuilder createDstL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix dstip) {
1760
1761         EthernetMatchBuilder eth = new EthernetMatchBuilder();
1762         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
1763         ethTypeBuilder.setType(new EtherType(0x0800L));
1764         eth.setEthernetType(ethTypeBuilder.build());
1765         matchBuilder.setEthernetMatch(eth.build());
1766
1767         Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
1768         ipv4match.setIpv4Destination(dstip);
1769
1770         matchBuilder.setLayer3Match(ipv4match.build());
1771
1772         return matchBuilder;
1773
1774     }
1775
1776     /**
1777      * @param matchBuilder MatchBuilder Object without a match yet
1778      * @param srcip        String containing an IPv4 prefix
1779      * @return             matchBuilder Map Object with a match
1780      */
1781     private static MatchBuilder createSrcL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix srcip) {
1782
1783         EthernetMatchBuilder eth = new EthernetMatchBuilder();
1784         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
1785         ethTypeBuilder.setType(new EtherType(0x0800L));
1786         eth.setEthernetType(ethTypeBuilder.build());
1787         matchBuilder.setEthernetMatch(eth.build());
1788
1789         Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder();
1790         Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
1791         ipv4match.setIpv4Source(srcip);
1792         matchBuilder.setLayer3Match(ipv4match.build());
1793
1794         return matchBuilder;
1795
1796     }
1797
1798     /**
1799      * Create Source TCP Port Match
1800      *
1801      * @param matchBuilder @param matchbuilder MatchBuilder Object without a match yet
1802      * @param tcpport      Integer representing a source TCP port
1803      * @return             matchBuilder Map MatchBuilder Object with a match
1804      */
1805     protected static MatchBuilder createSetSrcTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) {
1806
1807         EthernetMatchBuilder ethType = new EthernetMatchBuilder();
1808         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
1809         ethTypeBuilder.setType(new EtherType(0x0800L));
1810         ethType.setEthernetType(ethTypeBuilder.build());
1811         matchBuilder.setEthernetMatch(ethType.build());
1812
1813         IpMatchBuilder ipmatch = new IpMatchBuilder();
1814         ipmatch.setIpProtocol((short) 6);
1815         matchBuilder.setIpMatch(ipmatch.build());
1816
1817         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
1818         tcpmatch.setTcpSourcePort(tcpport);
1819         matchBuilder.setLayer4Match(tcpmatch.build());
1820
1821         return matchBuilder;
1822
1823     }
1824
1825     /**
1826      * Create Destination TCP Port Match
1827      *
1828      * @param matchBuilder MatchBuilder Object without a match yet
1829      * @param tcpport      Integer representing a destination TCP port
1830      * @return             matchBuilder Map MatchBuilder Object with a match
1831      */
1832     protected static MatchBuilder createSetDstTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) {
1833
1834         EthernetMatchBuilder ethType = new EthernetMatchBuilder();
1835         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
1836         ethTypeBuilder.setType(new EtherType(0x0800L));
1837         ethType.setEthernetType(ethTypeBuilder.build());
1838         matchBuilder.setEthernetMatch(ethType.build());
1839
1840         IpMatchBuilder ipmatch = new IpMatchBuilder();
1841         ipmatch.setIpProtocol((short) 6);
1842         matchBuilder.setIpMatch(ipmatch.build());
1843
1844         PortNumber dstport = new PortNumber(tcpport);
1845         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
1846
1847         tcpmatch.setTcpDestinationPort(tcpport);
1848         matchBuilder.setLayer4Match(tcpmatch.build());
1849
1850         return matchBuilder;
1851     }
1852
1853     /**
1854      * Create Send to Controller Reserved Port Instruction (packet_in)
1855      *
1856      * @param ib Map InstructionBuilder without any instructions
1857      * @return ib Map InstructionBuilder with instructions
1858      */
1859
1860     protected static InstructionBuilder createSendToControllerInstructions(InstructionBuilder ib) {
1861
1862         List<Action> actionList = new ArrayList<Action>();
1863         ActionBuilder ab = new ActionBuilder();
1864
1865         OutputActionBuilder output = new OutputActionBuilder();
1866         output.setMaxLength(56);
1867         Uri value = new Uri("CONTROLLER");
1868         output.setOutputNodeConnector(value);
1869         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
1870         ab.setOrder(0);
1871         ab.setKey(new ActionKey(0));
1872         actionList.add(ab.build());
1873
1874         // Create an Apply Action
1875         ApplyActionsBuilder aab = new ApplyActionsBuilder();
1876         aab.setAction(actionList);
1877
1878         // Wrap our Apply Action in an Instruction
1879         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1880
1881         return ib;
1882     }
1883
1884     /**
1885      * Create Output Port Instruction
1886      *
1887      * @param ib       Map InstructionBuilder without any instructions
1888      * @param dpidLong Long the datapath ID of a switch/node
1889      * @param port     Long representing a port on a switch/node
1890      * @return ib InstructionBuilder Map with instructions
1891      */
1892     protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port) {
1893
1894         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
1895         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, port);
1896
1897         List<Action> actionList = new ArrayList<Action>();
1898         ActionBuilder ab = new ActionBuilder();
1899         OutputActionBuilder oab = new OutputActionBuilder();
1900         oab.setOutputNodeConnector(ncid);
1901
1902         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
1903         ab.setOrder(0);
1904         ab.setKey(new ActionKey(0));
1905         actionList.add(ab.build());
1906
1907         // Create an Apply Action
1908         ApplyActionsBuilder aab = new ApplyActionsBuilder();
1909         aab.setAction(actionList);
1910         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1911
1912         return ib;
1913     }
1914
1915     /**
1916      * Create Output Port Instruction
1917      *
1918      * @param ib       Map InstructionBuilder without any instructions
1919      * @param dpidLong Long the datapath ID of a switch/node
1920      * @param port     Long representing a port on a switch/node
1921      * @return ib InstructionBuilder Map with instructions
1922      */
1923     protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port , List<Instruction> instructions) {
1924
1925         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
1926         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1927
1928         List<Action> actionList = new ArrayList<Action>();
1929         ActionBuilder ab = new ActionBuilder();
1930
1931         List<Action> existingActions = null;
1932         if (instructions != null) {
1933             for (Instruction in : instructions) {
1934                 if (in.getInstruction() instanceof ApplyActionsCase) {
1935                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1936                     actionList.addAll(existingActions);
1937                 }
1938             }
1939         }
1940
1941         OutputActionBuilder oab = new OutputActionBuilder();
1942         oab.setOutputNodeConnector(ncid);
1943         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
1944         ab.setOrder(0);
1945         ab.setKey(new ActionKey(0));
1946         Action newAction = ab.build();
1947         boolean addNew = true;
1948         for (Action action : actionList) {
1949             if (action.getAction() instanceof OutputActionCase) {
1950                 OutputActionCase opAction = (OutputActionCase)action.getAction();
1951                 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1952                     addNew = false;
1953                     break;
1954                 }
1955             }
1956         }
1957         if (addNew) actionList.add(newAction);
1958
1959         // Create an Apply Action
1960         ApplyActionsBuilder aab = new ApplyActionsBuilder();
1961         aab.setAction(actionList);
1962         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1963
1964         return ib;
1965     }
1966
1967     /**
1968     * Remove Output Port from Instruction
1969     *
1970     * @param ib Map InstructionBuilder without any instructions
1971     * @param dpidLong Long the datapath ID of a switch/node
1972     * @param port Long representing a port on a switch/node
1973     * @return ib InstructionBuilder Map with instructions
1974     */
1975     protected static boolean removeOutputPortFromInstructions(InstructionBuilder ib,
1976                                    Long dpidLong, Long port , List<Instruction> instructions) {
1977
1978         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
1979         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1980
1981         List<Action> actionList = new ArrayList<Action>();
1982         ActionBuilder ab = new ActionBuilder();
1983
1984         List<Action> existingActions = null;
1985         if (instructions != null) {
1986             for (Instruction in : instructions) {
1987                 if (in.getInstruction() instanceof ApplyActionsCase) {
1988                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1989                     actionList.addAll(existingActions);
1990                     break;
1991                 }
1992             }
1993         }
1994
1995         int numOutputPort = 0;
1996         for (Action action : actionList) {
1997             if (action.getAction() instanceof OutputActionCase) {
1998                 numOutputPort++;
1999                 OutputActionCase opAction = (OutputActionCase)action.getAction();
2000                 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
2001                     /* Find the output port in action list and remove */
2002                     actionList.remove(action);
2003                     numOutputPort--;
2004                     break;
2005                 }
2006             }
2007         }
2008
2009         /* Put new action list in Apply Action instruction */
2010         if (numOutputPort > 0) {
2011             ApplyActionsBuilder aab = new ApplyActionsBuilder();
2012             aab.setAction(actionList);
2013             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2014             return false;
2015         } else {
2016             /* if all output port are removed. Return true to indicate flow remove */
2017             return true;
2018         }
2019     }
2020
2021     /**
2022      * Create Set Vlan ID Instruction
2023      *
2024      * @param ib     Map InstructionBuilder without any instructions
2025      * @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID
2026      * @return ib Map InstructionBuilder with instructions
2027      */
2028     protected static InstructionBuilder createSetVlanInstructions(InstructionBuilder ib, VlanId vlanId) {
2029
2030         List<Action> actionList = new ArrayList<Action>();
2031         ActionBuilder ab = new ActionBuilder();
2032
2033         SetVlanIdActionBuilder vl = new SetVlanIdActionBuilder();
2034         vl.setVlanId(vlanId);
2035         ab.setAction(new SetVlanIdActionCaseBuilder().setSetVlanIdAction(vl.build()).build());
2036         actionList.add(ab.build());
2037         // Create an Apply Action
2038         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2039         aab.setAction(actionList);
2040
2041         // Wrap our Apply Action in an Instruction
2042         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2043
2044         return ib;
2045     }
2046
2047     /**
2048      * Create Set IPv4 Destination Instruction
2049      *
2050      * @param ib Map InstructionBuilder without any instructions
2051      * @return ib Map InstructionBuilder with instructions
2052      */
2053     protected static InstructionBuilder createStripVlanInstructions(InstructionBuilder ib) {
2054
2055         StripVlanActionBuilder stripVlanActionBuilder = new StripVlanActionBuilder();
2056         StripVlanAction vlanAction = stripVlanActionBuilder.build();
2057         ActionBuilder ab = new ActionBuilder();
2058         ab.setAction(new StripVlanActionCaseBuilder().setStripVlanAction(vlanAction).build());
2059
2060         // Add our drop action to a list
2061         List<Action> actionList = new ArrayList<Action>();
2062         actionList.add(ab.build());
2063
2064         // Create an Apply Action
2065         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2066         aab.setAction(actionList);
2067
2068         // Wrap our Apply Action in an Instruction
2069         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2070
2071         return ib;
2072     }
2073
2074     /**
2075      * Create Set IPv4 Source Instruction
2076      *
2077      * @param ib        Map InstructionBuilder without any instructions
2078      * @param prefixsrc String containing an IPv4 prefix
2079      * @return ib Map InstructionBuilder with instructions
2080      */
2081     protected static InstructionBuilder createNwSrcInstructions(InstructionBuilder ib, Ipv4Prefix prefixsrc) {
2082
2083         List<Action> actionList = new ArrayList<Action>();
2084         ActionBuilder ab = new ActionBuilder();
2085
2086         SetNwSrcActionBuilder setNwsrcActionBuilder = new SetNwSrcActionBuilder();
2087         Ipv4Builder ipsrc = new Ipv4Builder();
2088         ipsrc.setIpv4Address(prefixsrc);
2089         setNwsrcActionBuilder.setAddress(ipsrc.build());
2090         ab.setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwsrcActionBuilder.build()).build());
2091         actionList.add(ab.build());
2092
2093         // Create an Apply Action
2094         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2095         aab.setAction(actionList);
2096
2097         // Wrap our Apply Action in an Instruction
2098         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2099
2100         return ib;
2101     }
2102
2103     /**
2104      * Create Set IPv4 Destination Instruction
2105      *
2106      * @param ib           Map InstructionBuilder without any instructions
2107      * @param prefixdst    String containing an IPv4 prefix
2108      * @return ib Map InstructionBuilder with instructions
2109      */
2110     protected static InstructionBuilder createNwDstInstructions(InstructionBuilder ib, Ipv4Prefix prefixdst) {
2111
2112         List<Action> actionList = new ArrayList<Action>();
2113         ActionBuilder ab = new ActionBuilder();
2114
2115         SetNwDstActionBuilder setNwDstActionBuilder = new SetNwDstActionBuilder();
2116         Ipv4Builder ipdst = new Ipv4Builder();
2117         ipdst.setIpv4Address(prefixdst);
2118         setNwDstActionBuilder.setAddress(ipdst.build());
2119         ab.setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilder.build()).build());
2120         actionList.add(ab.build());
2121
2122         // Create an Apply Action
2123         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2124         aab.setAction(actionList);
2125
2126         // Wrap our Apply Action in an Instruction
2127         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2128
2129         return ib;
2130     }
2131
2132     /**
2133      * Create Drop Instruction
2134      *
2135      * @param ib Map InstructionBuilder without any instructions
2136      * @return ib Map InstructionBuilder with instructions
2137      */
2138     protected static InstructionBuilder createDropInstructions(InstructionBuilder ib) {
2139
2140         DropActionBuilder dab = new DropActionBuilder();
2141         DropAction dropAction = dab.build();
2142         ActionBuilder ab = new ActionBuilder();
2143         ab.setAction(new DropActionCaseBuilder().setDropAction(dropAction).build());
2144
2145         // Add our drop action to a list
2146         List<Action> actionList = new ArrayList<Action>();
2147         actionList.add(ab.build());
2148
2149         // Create an Apply Action
2150         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2151         aab.setAction(actionList);
2152
2153         // Wrap our Apply Action in an Instruction
2154         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2155
2156         return ib;
2157     }
2158
2159     /**
2160      * Create GOTO Table Instruction Builder
2161      *
2162      * @param ib      Map InstructionBuilder without any instructions
2163      * @param tableId short representing a flow table ID short representing a flow table ID
2164      * @return ib Map InstructionBuilder with instructions
2165      */
2166     protected static InstructionBuilder createGotoTableInstructions(InstructionBuilder ib, short tableId) {
2167
2168         GoToTableBuilder gttb = new GoToTableBuilder();
2169         gttb.setTableId(tableId);
2170
2171         // Wrap our Apply Action in an InstructionBuilder
2172         ib.setInstruction(new GoToTableCaseBuilder().setGoToTable(gttb.build()).build());
2173
2174         return ib;
2175     }
2176
2177     /**
2178      * Create Set Tunnel ID Instruction Builder
2179      *
2180      * @param ib       Map InstructionBuilder without any instructions
2181      * @param tunnelId BigInteger representing a tunnel ID
2182      * @return ib Map InstructionBuilder with instructions
2183      */
2184     protected static InstructionBuilder createSetTunnelIdInstructions(InstructionBuilder ib, BigInteger tunnelId) {
2185
2186         List<Action> actionList = new ArrayList<Action>();
2187         ActionBuilder ab = new ActionBuilder();
2188         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2189
2190         // Build the Set Tunnel Field Action
2191         TunnelBuilder tunnel = new TunnelBuilder();
2192         tunnel.setTunnelId(tunnelId);
2193         setFieldBuilder.setTunnel(tunnel.build());
2194         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2195         actionList.add(ab.build());
2196
2197         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2198         aab.setAction(actionList);
2199
2200         // Wrap the Apply Action in an InstructionBuilder and return
2201         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2202
2203         return ib;
2204     }
2205
2206     /**
2207      * Create Set Source TCP Port Instruction
2208      *
2209      * @param ib      Map InstructionBuilder without any instructions
2210      * @param tcpport Integer representing a source TCP port
2211      * @return ib Map InstructionBuilder with instructions
2212      */
2213     protected static InstructionBuilder createSetSrcTCPPort(InstructionBuilder ib, PortNumber tcpport) {
2214
2215         List<Action> actionList = new ArrayList<Action>();
2216         ActionBuilder ab = new ActionBuilder();
2217         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2218
2219         // Build the Destination TCP Port
2220         PortNumber tcpsrcport = new PortNumber(tcpport);
2221         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
2222         tcpmatch.setTcpSourcePort(tcpsrcport);
2223
2224         setFieldBuilder.setLayer4Match(tcpmatch.build());
2225         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2226         ab.setKey(new ActionKey(1));
2227         actionList.add(ab.build());
2228
2229         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2230         aab.setAction(actionList);
2231         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2232
2233         return ib;
2234     }
2235
2236     /**
2237      * Create Set Destination TCP Port Instruction
2238      *
2239      * @param ib      Map InstructionBuilder without any instructions
2240      * @param tcpport Integer representing a source TCP port
2241      * @return ib Map InstructionBuilder with instructions
2242      */
2243     protected static InstructionBuilder createSetDstTCPPort(InstructionBuilder ib, PortNumber tcpport) {
2244
2245         List<Action> actionList = new ArrayList<Action>();
2246         ActionBuilder ab = new ActionBuilder();
2247         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2248
2249         // Build the Destination TCP Port
2250         PortNumber tcpdstport = new PortNumber(tcpport);
2251         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
2252         tcpmatch.setTcpDestinationPort(tcpdstport);
2253
2254         setFieldBuilder.setLayer4Match(tcpmatch.build());
2255         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2256         ab.setKey(new ActionKey(1));
2257         actionList.add(ab.build());
2258
2259         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2260         aab.setAction(actionList);
2261         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2262
2263         return ib;
2264     }
2265
2266     /**
2267      * Create Set Source UDP Port Instruction
2268      *
2269      * @param ib      Map InstructionBuilder without any instructions
2270      * @param udpport Integer representing a source UDP port
2271      * @return ib Map InstructionBuilder with instructions
2272      */
2273     protected static InstructionBuilder createSetSrcUDPPort(InstructionBuilder ib, PortNumber udpport) {
2274
2275         List<Action> actionList = new ArrayList<Action>();
2276         ActionBuilder ab = new ActionBuilder();
2277         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2278
2279         // Build the Destination TCP Port
2280         PortNumber udpsrcport = new PortNumber(udpport);
2281         UdpMatchBuilder udpmatch = new UdpMatchBuilder();
2282         udpmatch.setUdpSourcePort(udpsrcport);
2283
2284         setFieldBuilder.setLayer4Match(udpmatch.build());
2285         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2286         ab.setKey(new ActionKey(1));
2287         actionList.add(ab.build());
2288
2289         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2290         aab.setAction(actionList);
2291         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2292
2293         return ib;
2294     }
2295
2296     /**
2297      * Create Set Destination UDP Port Instruction
2298      *
2299      * @param ib      Map InstructionBuilder without any instructions
2300      * @param udpport Integer representing a destination UDP port
2301      * @return ib Map InstructionBuilder with instructions
2302      */
2303     protected static InstructionBuilder createSetDstUDPPort(InstructionBuilder ib, PortNumber udpport) {
2304
2305         List<Action> actionList = new ArrayList<Action>();
2306         ActionBuilder ab = new ActionBuilder();
2307         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2308
2309         // Build the Destination TCP Port
2310         PortNumber udpdstport = new PortNumber(udpport);
2311         UdpMatchBuilder udpmatch = new UdpMatchBuilder();
2312         udpmatch.setUdpDestinationPort(udpdstport);
2313
2314         setFieldBuilder.setLayer4Match(udpmatch.build());
2315         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2316         ab.setKey(new ActionKey(1));
2317         actionList.add(ab.build());
2318
2319         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2320         aab.setAction(actionList);
2321         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2322
2323         return ib;
2324     }
2325
2326     /**
2327      * Create Set ICMP Code Instruction
2328      *
2329      * @param ib   Map InstructionBuilder without any instructions
2330      * @param code short repesenting an ICMP code
2331      * @return ib Map InstructionBuilder with instructions
2332      */
2333
2334     private static InstructionBuilder createSetIcmpCodeInstruction(InstructionBuilder ib, short code) {
2335
2336         List<Action> actionList = new ArrayList<Action>();
2337         ActionBuilder ab = new ActionBuilder();
2338         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2339         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
2340
2341         // Build the ICMPv4 Code Match
2342         icmpv4match.setIcmpv4Code(code);
2343         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
2344
2345         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2346         ab.setKey(new ActionKey(0));
2347         actionList.add(ab.build());
2348         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2349         aab.setAction(actionList);
2350
2351         // Wrap our Apply Action in an Instruction
2352         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2353
2354         return ib;
2355     }
2356
2357     /**
2358      * Create Set ICMP Code Instruction
2359      *
2360      * @param ib Map InstructionBuilder without any instructions
2361      * @return ib Map InstructionBuilder with instructions
2362      */
2363     private static InstructionBuilder createSetIcmpTypeInstruction(InstructionBuilder ib, short type) {
2364
2365         List<Action> actionList = new ArrayList<Action>();
2366         ActionBuilder ab = new ActionBuilder();
2367         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2368         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
2369
2370         // Build the ICMPv4 Code Match
2371         icmpv4match.setIcmpv4Code(type);
2372         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
2373
2374         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2375         ab.setKey(new ActionKey(1));
2376         actionList.add(ab.build());
2377         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2378         aab.setAction(actionList);
2379
2380         // Wrap our Apply Action in an Instruction
2381         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2382
2383         return ib;
2384     }
2385
2386     /**
2387      * Create Decrement TTL Instruction
2388      *
2389      * @param ib Map InstructionBuilder without any instructions
2390      * @return ib Map InstructionBuilder with instructions
2391      */
2392     private static InstructionBuilder createDecNwTtlInstructions(InstructionBuilder ib) {
2393         DecNwTtlBuilder decNwTtlBuilder = new DecNwTtlBuilder();
2394         DecNwTtl decNwTtl = decNwTtlBuilder.build();
2395         ActionBuilder ab = new ActionBuilder();
2396         ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build());
2397
2398         // Add our drop action to a list
2399         List<Action> actionList = new ArrayList<Action>();
2400         actionList.add(ab.build());
2401
2402         // Create an Apply Action
2403         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2404         aab.setAction(actionList);
2405
2406         // Wrap our Apply Action in an Instruction
2407         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
2408
2409         return ib;
2410     }
2411
2412     /**
2413      * Set Src Arp MAC
2414      */
2415     private static InstructionBuilder createSrcArpMacInstructions(InstructionBuilder ib, MacAddress macsrc) {
2416
2417         List<Action> actionList = new ArrayList<Action>();
2418         ActionBuilder ab = new ActionBuilder();
2419
2420         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2421         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
2422         ArpSourceHardwareAddressBuilder arpsrc = new ArpSourceHardwareAddressBuilder();
2423         arpsrc.setAddress(macsrc);
2424         arpmatch.setArpSourceHardwareAddress(arpsrc.build());
2425         setFieldBuilder.setLayer3Match(arpmatch.build());
2426         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2427         ab.setKey(new ActionKey(0));
2428         actionList.add(ab.build());
2429
2430         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2431         aab.setAction(actionList);
2432
2433         return ib;
2434     }
2435
2436     /**
2437      * Set Dst Arp MAC
2438      */
2439     private static InstructionBuilder createDstArpMacInstructions(InstructionBuilder ib, MacAddress macdst) {
2440
2441         List<Action> actionList = new ArrayList<Action>();
2442         ActionBuilder ab = new ActionBuilder();
2443         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2444
2445         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
2446         ArpTargetHardwareAddressBuilder arpdst = new ArpTargetHardwareAddressBuilder();
2447         arpdst.setAddress(macdst);
2448         setFieldBuilder.setLayer3Match(arpmatch.build());
2449         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2450         ab.setKey(new ActionKey(0));
2451         actionList.add(ab.build());
2452
2453         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2454         aab.setAction(actionList);
2455
2456         return ib;
2457     }
2458
2459     /**
2460      * Set Dst Arp IP
2461      */
2462     private static InstructionBuilder createDstArpIpInstructions(InstructionBuilder ib, Ipv4Prefix dstiparp) {
2463
2464         List<Action> actionList = new ArrayList<Action>();
2465         ActionBuilder ab = new ActionBuilder();
2466         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2467
2468         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
2469         arpmatch.setArpTargetTransportAddress(dstiparp);
2470         setFieldBuilder.setLayer3Match(arpmatch.build());
2471         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2472         ab.setKey(new ActionKey(0));
2473         actionList.add(ab.build());
2474
2475         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2476         aab.setAction(actionList);
2477
2478         return ib;
2479     }
2480
2481     /**
2482      * Set Src Arp IP
2483      */
2484     private static InstructionBuilder createSrcArpIpInstructions(InstructionBuilder ib, Ipv4Prefix srciparp) {
2485
2486         List<Action> actionList = new ArrayList<Action>();
2487         ActionBuilder ab = new ActionBuilder();
2488         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
2489
2490         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
2491         arpmatch.setArpSourceTransportAddress(srciparp);
2492         setFieldBuilder.setLayer3Match(arpmatch.build());
2493         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
2494         ab.setKey(new ActionKey(0));
2495         actionList.add(ab.build());
2496
2497         ApplyActionsBuilder aab = new ApplyActionsBuilder();
2498         aab.setAction(actionList);
2499
2500         return ib;
2501     }
2502
2503     @Override
2504     public void initializeOFFlowRules(Node openflowNode) {
2505         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
2506         List<Node> ovsNodes = connectionService.getNodes();
2507         if (ovsNodes == null) return;
2508         for (Node ovsNode : ovsNodes) {
2509             Long dpid = this.getIntegrationBridgeOFDPID(ovsNode);
2510             logger.debug("Compare openflowNode to OVS br-int node {} vs {}", openflowNode.getID(), dpid);
2511             String openflowID = ""+openflowNode.getID();
2512             if (openflowID.contains(""+dpid)) {
2513                 this.initializeFlowRules(ovsNode, adminConfigManager.getIntegrationBridgeName());
2514                 this.triggerInterfaceUpdates(ovsNode);
2515             }
2516         }
2517     }
2518
2519     private NodeBuilder createNodeBuilder(String nodeId) {
2520         NodeBuilder builder = new NodeBuilder();
2521         builder.setId(new NodeId(nodeId));
2522         builder.setKey(new NodeKey(builder.getId()));
2523         return builder;
2524     }
2525
2526     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder
2527                                                                                                                                              node) {
2528         return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
2529                 node.getKey()).toInstance();
2530     }
2531
2532     private String getInternalBridgeUUID (Node node, String bridgeName) {
2533         try {
2534             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
2535             Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
2536             if (bridgeTable == null) return null;
2537             for (String key : bridgeTable.keySet()) {
2538                 Bridge bridge = (Bridge)bridgeTable.get(key);
2539                 if (bridge.getName().equals(bridgeName)) return key;
2540             }
2541         } catch (Exception e) {
2542             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
2543         }
2544         return null;
2545     }
2546 }