2e43b49ad8af8e0cec76c78c30a371d95a18bc32
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / OF13Provider.java
1 /**
2  * Copyright (C) 2013 Red Hat, Inc.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Authors : Madhu Venugopal, Brent Salisbury, Dave Tucker
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt.providers;
11
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.CheckedFuture;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
16 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
21 import org.opendaylight.controller.sal.core.Node;
22 import org.opendaylight.controller.sal.utils.HexEncode;
23 import org.opendaylight.controller.sal.utils.Status;
24 import org.opendaylight.controller.sal.utils.StatusCode;
25 import org.opendaylight.ovsdb.lib.notation.Row;
26 import org.opendaylight.ovsdb.lib.notation.UUID;
27 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
28 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
29 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
30 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
31 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
32 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
34 import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
35 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
36 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
37 import org.opendaylight.ovsdb.schema.openvswitch.Port;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
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.list.Action;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
122 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
123
124 import com.google.common.base.Preconditions;
125 import com.google.common.collect.Lists;
126 import com.google.common.collect.Maps;
127 import org.slf4j.Logger;
128 import org.slf4j.LoggerFactory;
129
130 import java.math.BigInteger;
131 import java.net.InetAddress;
132 import java.util.List;
133 import java.util.Map;
134 import java.util.Set;
135 import java.util.concurrent.ExecutionException;
136
137 /**
138  * Open vSwitch OpenFlow 1.3 Networking Provider for OpenStack Neutron
139  */
140 public class OF13Provider implements NetworkingProvider {
141     private static final Logger logger = LoggerFactory.getLogger(OF13Provider.class);
142     private DataBroker dataBroker;
143     private static final short TABLE_0_DEFAULT_INGRESS = 0;
144     private static final short TABLE_1_ISOLATE_TENANT = 10;
145     private static final short TABLE_2_LOCAL_FORWARD = 20;
146     private static Long groupId = 1L;
147
148     private volatile org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService configurationService;
149     private volatile BridgeConfigurationManager bridgeConfigurationManager;
150     private volatile TenantNetworkManager tenantNetworkManager;
151     private volatile OvsdbConfigurationService ovsdbConfigurationService;
152     private volatile OvsdbConnectionService connectionService;
153     private volatile MdsalConsumer mdsalConsumer;
154
155     public OF13Provider(){
156
157     }
158
159     @Override
160     public boolean hasPerTenantTunneling() {
161         return false;
162     }
163
164     private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
165         InetAddress srcTunnelEndPoint = configurationService.getTunnelEndPoint(node);
166         if (srcTunnelEndPoint == null) {
167             logger.error("Tunnel Endpoint not configured for Node {}", node);
168             return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
169         }
170
171         if (!bridgeConfigurationManager.isNodeNeutronReady(node)) {
172             logger.error(node+" is not Overlay ready");
173             return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
174         }
175
176         if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
177             logger.debug(node+" has no VM corresponding to segment "+ tunnelKey);
178             return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey);
179         }
180         return new Status(StatusCode.SUCCESS);
181     }
182
183     private String getTunnelName(String tunnelType, InetAddress dst) {
184         return tunnelType+"-"+dst.getHostAddress();
185     }
186
187     private boolean isTunnelPresent(Node node, String tunnelName, String bridgeUUID) throws Exception {
188         Preconditions.checkNotNull(ovsdbConfigurationService);
189         Row bridgeRow = ovsdbConfigurationService
190                 .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUUID);
191         Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
192         if (bridge != null) {
193             Set<UUID> ports = bridge.getPortsColumn().getData();
194             for (UUID portUUID : ports) {
195                 Row portRow = ovsdbConfigurationService
196                         .getRow(node, ovsdbConfigurationService.getTableName(node, Port.class), portUUID.toString());
197                 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
198                 if (port != null && tunnelName.equalsIgnoreCase(port.getName())) return true;
199             }
200         }
201         return false;
202     }
203
204     private String getPortUuid(Node node, String name, String bridgeUUID) throws Exception {
205         Preconditions.checkNotNull(ovsdbConfigurationService);
206         Row bridgeRow = ovsdbConfigurationService
207                 .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUUID);
208         Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
209         if (bridge != null) {
210             Set<UUID> ports = bridge.getPortsColumn().getData();
211             for (UUID portUUID : ports) {
212                 Row portRow = ovsdbConfigurationService
213                         .getRow(node, ovsdbConfigurationService.getTableName(node, Port.class), portUUID.toString());
214                 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
215                 if (port != null && name.equalsIgnoreCase(port.getName())) return portUUID.toString();
216             }
217         }
218         return null;
219     }
220
221     private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
222         Preconditions.checkNotNull(ovsdbConfigurationService);
223         try {
224             String bridgeUUID = null;
225             String tunnelBridgeName = configurationService.getIntegrationBridgeName();
226             Map<String, Row> bridgeTable = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
227             if (bridgeTable != null) {
228                 for (String uuid : bridgeTable.keySet()) {
229                     Bridge bridge = ovsdbConfigurationService.getTypedRow(node,Bridge.class, bridgeTable.get(uuid));
230                     if (bridge.getName().equals(tunnelBridgeName)) {
231                         bridgeUUID = uuid;
232                         break;
233                     }
234                 }
235             }
236             if (bridgeUUID == null) {
237                 logger.error("Could not find Bridge {} in {}", tunnelBridgeName, node);
238                 return new Status(StatusCode.NOTFOUND, "Could not find "+tunnelBridgeName+" in "+node);
239             }
240             String portName = getTunnelName(tunnelType, dst);
241
242             if (this.isTunnelPresent(node, portName, bridgeUUID)) {
243                 logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node);
244                 return new Status(StatusCode.SUCCESS);
245             }
246
247             Port tunnelPort = ovsdbConfigurationService.createTypedRow(node, Port.class);
248             tunnelPort.setName(portName);
249             StatusWithUuid statusWithUuid = ovsdbConfigurationService
250                     .insertRow(node, ovsdbConfigurationService.getTableName(node, Port.class), bridgeUUID, tunnelPort.getRow());
251             if (!statusWithUuid.isSuccess()) {
252                 logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID);
253                 return statusWithUuid;
254             }
255
256             String tunnelPortUUID = statusWithUuid.getUuid().toString();
257             String interfaceUUID = null;
258             int timeout = 6;
259             while ((interfaceUUID == null) && (timeout > 0)) {
260                 Row portRow = ovsdbConfigurationService
261                         .getRow(node, ovsdbConfigurationService.getTableName(node, Port.class), tunnelPortUUID);
262                 tunnelPort = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
263                 Set<UUID> interfaces = tunnelPort.getInterfacesColumn().getData();
264                 if (interfaces == null || interfaces.size() == 0) {
265                     // Wait for the OVSDB update to sync up the Local cache.
266                     Thread.sleep(500);
267                     timeout--;
268                     continue;
269                 }
270                 interfaceUUID = interfaces.toArray()[0].toString();
271                 Row intfRow = ovsdbConfigurationService
272                         .getRow(node, ovsdbConfigurationService.getTableName(node, Interface.class), interfaceUUID);
273                 Interface intf = ovsdbConfigurationService.getTypedRow(node, Interface.class, intfRow);
274                 if (intf == null) interfaceUUID = null;
275             }
276
277             if (interfaceUUID == null) {
278                 logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID);
279                 return new Status(StatusCode.INTERNALERROR);
280             }
281
282             Interface tunInterface = ovsdbConfigurationService.createTypedRow(node, Interface.class);
283             tunInterface.setType(tunnelType);
284             Map<String, String> options = Maps.newHashMap();
285             options.put("key", "flow");
286             options.put("local_ip", src.getHostAddress());
287             options.put("remote_ip", dst.getHostAddress());
288             tunInterface.setOptions(options);
289             Status status = ovsdbConfigurationService
290                     .updateRow(node, ovsdbConfigurationService.getTableName(node, Interface.class), tunnelPortUUID, interfaceUUID, tunInterface.getRow());
291             logger.debug("Tunnel {} add status : {}", tunInterface, status);
292             return status;
293         } catch (Exception e) {
294             logger.error("Exception in addTunnelPort", e);
295             return new Status(StatusCode.INTERNALERROR);
296         }
297     }
298
299     /* delete port from ovsdb port table */
300     private Status deletePort(Node node, String bridgeName, String portName) {
301         Preconditions.checkNotNull(ovsdbConfigurationService);
302         try {
303             String bridgeUUID = null;
304             Map<String, Row> bridgeTable = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
305             if (bridgeTable != null) {
306                 for (String uuid : bridgeTable.keySet()) {
307                     Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(uuid));
308                     if (bridge.getName().equals(bridgeName)) {
309                         bridgeUUID = uuid;
310                         break;
311                     }
312                 }
313             }
314             if (bridgeUUID == null) {
315                 logger.debug("Could not find Bridge {} in {}", bridgeName, node);
316                 return new Status(StatusCode.SUCCESS);
317             }
318
319             String portUUID = this.getPortUuid(node, portName, bridgeUUID);
320             Status status = new Status(StatusCode.SUCCESS);
321             if (portUUID != null) {
322                status = ovsdbConfigurationService
323                        .deleteRow(node, ovsdbConfigurationService.getTableName(node, Port.class), portUUID);
324                if (!status.isSuccess()) {
325                    logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID,
326                                 status);
327                    return status;
328                }
329                logger.debug("Port {} delete status : {}", portName, status);
330             }
331             return status;
332         } catch (Exception e) {
333             logger.error("Exception in deletePort", e);
334             return new Status(StatusCode.INTERNALERROR);
335         }
336     }
337
338     private Status deleteTunnelPort(Node node, String tunnelType, InetAddress src, InetAddress dst) {
339         String tunnelBridgeName = configurationService.getIntegrationBridgeName();
340         String portName = getTunnelName(tunnelType, dst);
341         return deletePort(node, tunnelBridgeName, portName);
342     }
343
344     private Status deletePhysicalPort(Node node, String phyIntfName) {
345         String intBridgeName = configurationService.getIntegrationBridgeName();
346         return deletePort(node, intBridgeName, phyIntfName);
347     }
348
349     private void programLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
350          /*
351          * Table(0) Rule #3
352          * ----------------
353          * Match: VM sMac and Local Ingress Port
354          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
355          */
356
357          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, true);
358
359         /*
360          * Table(0) Rule #4
361          * ----------------
362          * Match: Drop any remaining Ingress Local VM Packets
363          * Action: Drop w/ a low priority
364          */
365
366          handleDropSrcIface(dpid, localPort, true);
367
368          /*
369           * Table(2) Rule #1
370           * ----------------
371           * Match: Match TunID and Destination DL/dMAC Addr
372           * Action: Output Port
373           * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
374           */
375
376          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, true);
377
378          /*
379           * Table(2) Rule #2
380           * ----------------
381           * Match: Tunnel ID and dMAC (::::FF:FF)
382           * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
383           * actions=output:2,3,4,5
384           */
385
386           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
387
388           /*
389            * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
390            */
391           /*
392            * Table(1) Rule #3
393            * ----------------
394            * Match:  Any remaining Ingress Local VM Packets
395            * Action: Drop w/ a low priority
396            * -------------------------------------------
397            * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
398            */
399
400            handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, true);
401
402           /*
403            * Table(2) Rule #3
404            * ----------------
405            * Match: Any Remaining Flows w/a TunID
406            * Action: Drop w/ a low priority
407            * table=2,priority=8192,tun_id=0x5 actions=drop
408            */
409
410            handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, true);
411     }
412
413     private void removeLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
414         /*
415          * Table(0) Rule #3
416          * ----------------
417          * Match: VM sMac and Local Ingress Port
418          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
419          */
420
421          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, false);
422
423         /*
424          * Table(0) Rule #4
425          * ----------------
426          * Match: Drop any remaining Ingress Local VM Packets
427          * Action: Drop w/ a low priority
428          */
429
430          handleDropSrcIface(dpid, localPort, false);
431
432          /*
433           * Table(2) Rule #1
434           * ----------------
435           * Match: Match TunID and Destination DL/dMAC Addr
436           * Action: Output Port
437           * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
438           */
439
440          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, false);
441
442          /*
443           * Table(2) Rule #2
444           * ----------------
445           * Match: Tunnel ID and dMAC (::::FF:FF)
446           * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
447           * actions=output:2,3,4,5
448           */
449
450           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
451     }
452
453     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
454         /*
455          * Table(0) Rule #2
456          * ----------------
457          * Match: Ingress Port, Tunnel ID
458          * Action: GOTO Local Table (20)
459          */
460
461          handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
462
463          /*
464           * Table(1) Rule #2
465           * ----------------
466           * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
467           * Action: Flood to selected destination TEPs
468           * -------------------------------------------
469           * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
470           * actions=output:10,output:11,goto_table:2
471           */
472
473          handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
474
475     }
476
477     private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
478         /*
479          * Table(1) Rule #1
480          * ----------------
481          * Match: Drop any remaining Ingress Local VM Packets
482          * Action: Drop w/ a low priority
483          * -------------------------------------------
484          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
485          * actions=output:11,goto_table:2
486          */
487
488         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, true);
489     }
490
491     private void removeRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
492         /*
493          * Table(1) Rule #1
494          * ----------------
495          * Match: Drop any remaining Ingress Local VM Packets
496          * Action: Drop w/ a low priority
497          * -------------------------------------------
498          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
499          * actions=output:11,goto_table:2
500          */
501
502         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, false);
503     }
504
505     /* Remove tunnel rules if last node in this tenant network */
506     private void removePerTunnelRules(Node node, Long dpid, String segmentationId, long tunnelOFPort) {
507         /*
508          * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
509          */
510         /*
511          * Table(1) Rule #3
512          * ----------------
513          * Match:  Any remaining Ingress Local VM Packets
514          * Action: Drop w/ a low priority
515          * -------------------------------------------
516          * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
517          */
518
519         handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, false);
520
521         /*
522          * Table(2) Rule #3
523          * ----------------
524          * Match: Any Remaining Flows w/a TunID
525          * Action: Drop w/ a low priority
526          * table=2,priority=8192,tun_id=0x5 actions=drop
527          */
528
529         handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
530
531         /*
532          * Table(0) Rule #2
533          * ----------------
534          * Match: Ingress Port, Tunnel ID
535          * Action: GOTO Local Table (10)
536          */
537
538         handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
539
540          /*
541           * Table(1) Rule #2
542           * ----------------
543           * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
544           * Action: Flood to selected destination TEPs
545           * -------------------------------------------
546           * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
547           * actions=output:10,output:11,goto_table:2
548           */
549
550         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
551     }
552
553     private void programLocalVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
554         /*
555          * Table(0) Rule #1
556          * ----------------
557          * Match: VM sMac and Local Ingress Port
558          * Action: Set VLAN ID and GOTO Local Table 1
559          */
560
561         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
562                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
563                 attachedMac, true);
564
565         /*
566          * Table(0) Rule #3
567          * ----------------
568          * Match: Drop any remaining Ingress Local VM Packets
569          * Action: Drop w/ a low priority
570          */
571
572         handleDropSrcIface(dpid, localPort, true);
573
574         /*
575          * Table(2) Rule #1
576          * ----------------
577          * Match: Match VLAN ID and Destination DL/dMAC Addr
578          * Action: strip vlan, output to local port
579          * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
580          */
581
582         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
583                 localPort, attachedMac, true);
584
585         /*
586          * Table(2) Rule #2
587          * ----------------
588          * Match: VLAN ID and dMAC (::::FF:FF)
589          * Action: strip vlan, output to all local ports in this vlan
590          * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
591          * actions= strip_vlan, output:2,3,4,5
592          */
593
594         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
595                 localPort, true);
596
597          /*
598           * Table(2) Rule #3
599           * ----------------
600           * Match: Any Remaining Flows w/a VLAN ID
601           * Action: Drop w/ a low priority
602           * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
603           */
604
605           handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
606                                    true);
607    }
608
609     private void removeLocalVlanRules(Node node, Long dpid,
610                                       String segmentationId, String attachedMac,
611                                       long localPort) {
612         /*
613          * Table(0) Rule #1
614          * ----------------
615          * Match: VM sMac and Local Ingress Port
616          * Action: Set VLAN ID and GOTO Local Table 1
617          */
618
619         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
620                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
621                 attachedMac, false);
622
623         /*
624          * Table(0) Rule #3
625          * ----------------
626          * Match: Drop any remaining Ingress Local VM Packets
627          * Action: Drop w/ a low priority
628          */
629
630         handleDropSrcIface(dpid, localPort, false);
631
632         /*
633          * Table(2) Rule #1
634          * ----------------
635          * Match: Match VLAN ID and Destination DL/dMAC Addr
636          * Action: strip vlan, output to local port
637          * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
638          */
639
640         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
641                 localPort, attachedMac, false);
642
643         /*
644          * Table(2) Rule #2
645          * ----------------
646          * Match: VLAN ID and dMAC (::::FF:FF)
647          * Action: strip vlan, output to all local ports in this vlan
648          * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
649          * actions= strip_vlan, output:2,3,4,5
650          */
651
652         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
653                 localPort, false);
654    }
655
656    private void programLocalIngressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
657        /*
658         * Table(0) Rule #2
659         * ----------------
660         * Match: Ingress port = physical interface, Vlan ID
661         * Action: GOTO Local Table 2
662         */
663
664        handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
665                     segmentationId, ethPort, true);
666
667         /*
668          * Table(1) Rule #2
669          * ----------------
670          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
671          * Action: Flood to local and remote VLAN members
672          * -------------------------------------------
673          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
674          * actions=output:10 (eth port),goto_table:2
675          */
676
677         handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
678                            segmentationId, ethPort, true);
679    }
680
681    private void programRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
682        /*
683         * Table(1) Rule #1
684         * ----------------
685         * Match: Destination MAC is local VM MAC and vlan id
686         * Action: go to table 2
687         * -------------------------------------------
688         * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
689         * actions=goto_table:2
690         */
691
692        handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
693                      segmentationId, ethPort, attachedMac, true);
694
695        /*
696         * Table(1) Rule #3
697         * ----------------
698         * Match:  VLAN ID
699         * Action: Go to table 2
700         * -------------------------------------------
701         * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
702         */
703
704        handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
705                       segmentationId, ethPort, true);
706    }
707
708    private void removeRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
709        /*
710         * Table(1) Rule #1
711         * ----------------
712         * Match: Destination MAC is local VM MAC and vlan id
713         * Action: go to table 2
714         * -------------------------------------------
715         * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
716         * actions=goto_table:2
717         */
718
719        handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
720                      segmentationId, ethPort, attachedMac, false);
721    }
722
723    private void removePerVlanRules(Node node, Long dpid, String segmentationId, long ethPort) {
724        /*
725         * Table(2) Rule #3
726         * ----------------
727         * Match: Any Remaining Flows w/a VLAN ID
728         * Action: Drop w/ a low priority
729         * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
730         */
731
732         handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
733                                  false);
734
735         /*
736          * Table(0) Rule #2
737          * ----------------
738          * Match: Ingress port = physical interface, Vlan ID
739          * Action: GOTO Local Table 2
740          */
741
742         handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
743                      segmentationId, ethPort, false);
744
745          /*
746           * Table(1) Rule #2
747           * ----------------
748           * Match: Match VLAN ID and L2 ::::FF:FF Flooding
749           * Action: Flood to local and remote VLAN members
750           * -------------------------------------------
751           * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
752           * actions=output:10 (eth port),goto_table:2
753           */
754
755          handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
756                             segmentationId, ethPort, false);
757
758          /*
759           * Table(1) Rule #3
760           * ----------------
761           * Match:  VLAN ID
762           * Action: Go to table 2
763           * -------------------------------------------
764           * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
765           */
766
767          handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
768                         segmentationId, ethPort, false);
769    }
770     private Long getDpid (Node node, String bridgeUuid) {
771         Preconditions.checkNotNull(ovsdbConfigurationService);
772         try {
773             Row bridgeRow =  ovsdbConfigurationService
774                     .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUuid);
775             Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
776             Set<String> dpids = bridge.getDatapathIdColumn().getData();
777             if (dpids == null || dpids.size() == 0) return 0L;
778             return HexEncode.stringToLong((String) dpids.toArray()[0]);
779         } catch (Exception e) {
780             logger.error("Error finding Bridge's OF DPID", e);
781             return 0L;
782         }
783     }
784
785     private Long getIntegrationBridgeOFDPID (Node node) {
786         try {
787             String bridgeName = configurationService.getIntegrationBridgeName();
788             String brIntId = this.getInternalBridgeUUID(node, bridgeName);
789             if (brIntId == null) {
790                 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
791                 return 0L;
792             }
793
794             return getDpid(node, brIntId);
795         } catch (Exception e) {
796             logger.error("Error finding Integration Bridge's OF DPID", e);
797             return 0L;
798         }
799     }
800
801     private Long getExternalBridgeDpid (Node node) {
802         try {
803             String bridgeName = configurationService.getExternalBridgeName();
804             String brUuid = this.getInternalBridgeUUID(node, bridgeName);
805             if (brUuid == null) {
806                 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
807                 return 0L;
808             }
809
810             return getDpid(node, brUuid);
811         } catch (Exception e) {
812             logger.error("Error finding External Bridge's OF DPID", e);
813             return 0L;
814         }
815     }
816
817     private void programLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
818         try {
819             Long dpid = this.getIntegrationBridgeOFDPID(node);
820             if (dpid == 0L) {
821                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
822                 return;
823             }
824
825             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
826             if (of_ports == null || of_ports.size() <= 0) {
827                 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
828                 return;
829             }
830             long localPort = (Long)of_ports.toArray()[0];
831
832             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
833             if (externalIds == null) {
834                 logger.error("No external_ids seen in {}", intf);
835                 return;
836             }
837
838             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
839             if (attachedMac == null) {
840                 logger.error("No AttachedMac seen in {}", intf);
841                 return;
842             }
843
844             /* Program local rules based on network type */
845             if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
846                 logger.debug("Program local vlan rules for interface {}", intf.getName());
847                 programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
848             } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
849                        networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
850                 logger.debug("Program local bridge rules for interface {}", intf.getName());
851                 programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
852             }
853         } catch (Exception e) {
854             logger.error("Exception in programming Local Rules for "+intf+" on "+node, e);
855         }
856     }
857
858     private void removeLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
859         try {
860             Long dpid = this.getIntegrationBridgeOFDPID(node);
861             if (dpid == 0L) {
862                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
863                 return;
864             }
865
866             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
867             if (of_ports == null || of_ports.size() <= 0) {
868                 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
869                 return;
870             }
871             long localPort = (Long)of_ports.toArray()[0];
872
873             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
874             if (externalIds == null) {
875                 logger.error("No external_ids seen in {}", intf);
876                 return;
877             }
878
879             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
880             if (attachedMac == null) {
881                 logger.error("No AttachedMac seen in {}", intf);
882                 return;
883             }
884
885             /* Program local rules based on network type */
886             if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
887                 logger.debug("Remove local vlan rules for interface {}", intf.getName());
888                 removeLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
889             } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
890                        networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
891                 logger.debug("Remove local bridge rules for interface {}", intf.getName());
892                 removeLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
893             }
894         } catch (Exception e) {
895             logger.error("Exception in removing Local Rules for "+intf+" on "+node, e);
896         }
897     }
898
899     private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
900             Interface intf, boolean local) {
901
902         Preconditions.checkNotNull(ovsdbConfigurationService);
903
904         try {
905
906             Long dpid = this.getIntegrationBridgeOFDPID(node);
907             if (dpid == 0L) {
908                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
909                 return;
910             }
911
912             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
913             if (of_ports == null || of_ports.size() <= 0) {
914                 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
915                 return;
916             }
917             long localPort = (Long)of_ports.toArray()[0];
918
919             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
920             if (externalIds == null) {
921                 logger.error("No external_ids seen in {}", intf);
922                 return;
923             }
924
925             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
926             if (attachedMac == null) {
927                 logger.error("No AttachedMac seen in {}", intf);
928                 return;
929             }
930
931             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
932             if (intfs != null) {
933                 for (Row row : intfs.values()) {
934                     Interface tunIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
935                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
936                         of_ports = tunIntf.getOpenFlowPortColumn().getData();
937                         if (of_ports == null || of_ports.size() <= 0) {
938                             logger.debug("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
939                             continue;
940                         }
941                         long tunnelOFPort = (Long)of_ports.toArray()[0];
942
943                         if (tunnelOFPort == -1) {
944                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
945                             return;
946                         }
947                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
948
949                         if (!local) {
950                             programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
951                         }
952                         logger.trace("program local ingress tunnel rules: node" + node.getNodeIDString() + " intf " + intf.getName());
953                         if (local) {
954                             programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
955                         }
956                         return;
957                     }
958                 }
959             }
960         } catch (Exception e) {
961             logger.error("", e);
962         }
963     }
964
965     private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
966             Interface intf, boolean local, boolean isLastInstanceOnNode) {
967
968         Preconditions.checkNotNull(ovsdbConfigurationService);
969         try {
970
971             Long dpid = this.getIntegrationBridgeOFDPID(node);
972             if (dpid == 0L) {
973                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
974                 return;
975             }
976
977             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
978             if (of_ports == null || of_ports.size() <= 0) {
979                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
980                 return;
981             }
982             long localPort = (Long)of_ports.toArray()[0];
983
984             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
985             if (externalIds == null) {
986                 logger.error("No external_ids seen in {}", intf);
987                 return;
988             }
989
990             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
991             if (attachedMac == null) {
992                 logger.error("No AttachedMac seen in {}", intf);
993                 return;
994             }
995
996             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
997             if (intfs != null) {
998                 for (Row row : intfs.values()) {
999                     Interface tunIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1000                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
1001                         of_ports = tunIntf.getOpenFlowPortColumn().getData();
1002                         if (of_ports == null || of_ports.size() <= 0) {
1003                             logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
1004                             continue;
1005                         }
1006                         long tunnelOFPort = (Long)of_ports.toArray()[0];
1007
1008                         if (tunnelOFPort == -1) {
1009                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
1010                             return;
1011                         }
1012                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
1013
1014                         if (!local) {
1015                             removeRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
1016                         }
1017                         if (local && isLastInstanceOnNode) {
1018                             removePerTunnelRules(node, dpid, segmentationId, tunnelOFPort);
1019                         }
1020                         return;
1021                     }
1022                 }
1023             }
1024         } catch (Exception e) {
1025             logger.error("", e);
1026         }
1027     }
1028
1029     private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
1030         Preconditions.checkNotNull(ovsdbConfigurationService);
1031         logger.debug("Program vlan rules for interface {}", intf.getName());
1032         try {
1033
1034             Long dpid = this.getIntegrationBridgeOFDPID(node);
1035             if (dpid == 0L) {
1036                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1037                 return;
1038             }
1039
1040             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
1041             int timeout = 6;
1042             while ((of_ports == null) && (timeout > 0)) {
1043                 of_ports = intf.getOpenFlowPortColumn().getData();
1044                 if (of_ports == null || of_ports.size() <= 0) {
1045                     // Wait for the OVSDB update to sync up the Local cache.
1046                     Thread.sleep(500);
1047                     timeout--;
1048                 }
1049             }
1050             if (of_ports == null || of_ports.size() <= 0) {
1051                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
1052                 return;
1053             }
1054
1055             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
1056             if (externalIds == null) {
1057                 logger.error("No external_ids seen in {}", intf);
1058                 return;
1059             }
1060
1061             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
1062             if (attachedMac == null) {
1063                 logger.error("No AttachedMac seen in {}", intf);
1064                 return;
1065             }
1066
1067             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
1068             if (intfs != null) {
1069                 for (Row row : intfs.values()) {
1070                     Interface ethIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1071                     if (ethIntf.getName().equalsIgnoreCase(bridgeConfigurationManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork()))) {
1072                         of_ports = ethIntf.getOpenFlowPortColumn().getData();
1073                         timeout = 6;
1074                         while ((of_ports == null) && (timeout > 0)) {
1075                             of_ports = ethIntf.getOpenFlowPortColumn().getData();
1076                             if (of_ports == null || of_ports.size() <= 0) {
1077                                 // Wait for the OVSDB update to sync up the Local cache.
1078                                 Thread.sleep(500);
1079                                 timeout--;
1080                             }
1081                         }
1082
1083                         if (of_ports == null || of_ports.size() <= 0) {
1084                             logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
1085                             continue;
1086                         }
1087                         long ethOFPort = (Long)of_ports.toArray()[0];
1088
1089                         if (ethOFPort == -1) {
1090                             logger.error("Could NOT Identify eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1091                             throw new Exception("port number < 0");
1092                         }
1093                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1094
1095                         programRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1096                         programLocalIngressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1097                         return;
1098                     }
1099                 }
1100             }
1101         } catch (Exception e) {
1102             logger.error("", e);
1103         }
1104     }
1105
1106     private void removeVlanRules (NeutronNetwork network, Node node,
1107                       Interface intf, boolean isLastInstanceOnNode) {
1108         Preconditions.checkNotNull(ovsdbConfigurationService);
1109         logger.debug("Remove vlan rules for interface {}", intf.getName());
1110
1111         try {
1112
1113             Long dpid = this.getIntegrationBridgeOFDPID(node);
1114             if (dpid == 0L) {
1115                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1116                 return;
1117             }
1118
1119             Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
1120             if (of_ports == null || of_ports.size() <= 0) {
1121                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
1122                 return;
1123             }
1124
1125             Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
1126             if (externalIds == null) {
1127                 logger.error("No external_ids seen in {}", intf);
1128                 return;
1129             }
1130
1131             String attachedMac = externalIds.get(Constants.EXTERNAL_ID_VM_MAC);
1132             if (attachedMac == null) {
1133                 logger.error("No AttachedMac seen in {}", intf);
1134                 return;
1135             }
1136
1137             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
1138             if (intfs != null) {
1139                 for (Row row : intfs.values()) {
1140                     Interface ethIntf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1141                     if (ethIntf.getName().equalsIgnoreCase(bridgeConfigurationManager.getPhysicalInterfaceName(node,
1142                                                                    network.getProviderPhysicalNetwork()))) {
1143                         of_ports = ethIntf.getOpenFlowPortColumn().getData();
1144                         if (of_ports == null || of_ports.size() <= 0) {
1145                             logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
1146                             continue;
1147                         }
1148                         long ethOFPort = (Long)of_ports.toArray()[0];
1149
1150                         if (ethOFPort == -1) {
1151                             logger.error("Could NOT Identify eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1152                             throw new Exception("port number < 0");
1153                         }
1154                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
1155
1156                         removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
1157                         if (isLastInstanceOnNode) {
1158                             removePerVlanRules(node, dpid, network.getProviderSegmentationID(), ethOFPort);
1159                         }
1160                         return;
1161                     }
1162                 }
1163             }
1164         } catch (Exception e) {
1165             logger.error("", e);
1166         }
1167     }
1168
1169     @Override
1170     public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) {
1171         Preconditions.checkNotNull(connectionService);
1172         List<Node> nodes = connectionService.getNodes();
1173         nodes.remove(srcNode);
1174         this.programLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf);
1175
1176         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
1177             this.programVlanRules(network, srcNode, intf);
1178         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
1179                    || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)){
1180             for (Node dstNode : nodes) {
1181                 InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1182                 InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1183                 Status status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst);
1184                 if (status.isSuccess()) {
1185                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
1186                 }
1187                 addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
1188                 if (status.isSuccess()) {
1189                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
1190                 }
1191             }
1192         }
1193
1194         return new Status(StatusCode.SUCCESS);
1195     }
1196
1197     private Status triggerInterfaceUpdates(Node node) {
1198         Preconditions.checkNotNull(ovsdbConfigurationService);
1199         try {
1200             Map<String, Row> intfs = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
1201             if (intfs != null) {
1202                 for (Row row : intfs.values()) {
1203                     Interface intf = ovsdbConfigurationService.getTypedRow(node, Interface.class, row);
1204                     NeutronNetwork network = tenantNetworkManager.getTenantNetwork(intf);
1205                     logger.debug("Trigger Interface update for {}", intf);
1206                     if (network != null) {
1207                         this.handleInterfaceUpdate(network, node, intf);
1208                     }
1209                 }
1210             }
1211         } catch (Exception e) {
1212             logger.error("Error Triggering the lost interface updates for "+ node, e);
1213             return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage());
1214         }
1215         return new Status(StatusCode.SUCCESS);
1216     }
1217     @Override
1218     public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
1219         // TODO Auto-generated method stub
1220         return null;
1221     }
1222
1223     @Override
1224     public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf,
1225             boolean isLastInstanceOnNode) {
1226         Preconditions.checkNotNull(connectionService);
1227         Status status = new Status(StatusCode.SUCCESS);
1228         List<Node> nodes = connectionService.getNodes();
1229         nodes.remove(srcNode);
1230
1231         logger.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
1232         List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(srcNode);
1233         if (intf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
1234             || intf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
1235             /* Delete tunnel port */
1236             try {
1237                 Map<String, String> options = intf.getOptionsColumn().getData();
1238                 InetAddress src = InetAddress.getByName(options.get("local_ip"));
1239                 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
1240                 status = deleteTunnelPort(srcNode, intf.getTypeColumn().getData(), src, dst);
1241             } catch (Exception e) {
1242                 logger.error(e.getMessage(), e);
1243             }
1244         } else if (phyIfName.contains(intf.getName())) {
1245             deletePhysicalPort(srcNode, intf.getName());
1246         } else {
1247             /* delete all other interfaces */
1248             this.removeLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(),
1249                     srcNode, intf);
1250
1251             if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
1252                 this.removeVlanRules(network, srcNode,
1253                                  intf, isLastInstanceOnNode);
1254             } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
1255                    || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
1256
1257                 for (Node dstNode : nodes) {
1258                     InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1259                     InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1260                     logger.info("Remove tunnel rules for interface " + intf.getName() + " on srcNode" + srcNode.getNodeIDString());
1261                     this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
1262                                            dst, srcNode, intf, true, isLastInstanceOnNode);
1263                     logger.info("Remove tunnel rules for interface " + intf.getName() + " on dstNode" + dstNode.getNodeIDString());
1264                     this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
1265                                            src, dstNode, intf, false, isLastInstanceOnNode);
1266                 }
1267             }
1268         }
1269         return status;
1270     }
1271
1272     @Override
1273     public void initializeFlowRules(Node node) {
1274         this.initializeFlowRules(node, configurationService.getIntegrationBridgeName());
1275         this.initializeFlowRules(node, configurationService.getExternalBridgeName());
1276         this.triggerInterfaceUpdates(node);
1277     }
1278
1279     private void initializeFlowRules(Node node, String bridgeName) {
1280         String bridgeUuid = this.getInternalBridgeUUID(node, bridgeName);
1281         if (bridgeUuid == null) {
1282             return;
1283         }
1284
1285         Long dpid = getDpid(node, bridgeUuid);
1286
1287         if (dpid == 0L) {
1288             logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1289             return;
1290         }
1291
1292         /*
1293          * Table(0) Rule #1
1294          * ----------------
1295          * Match: LLDP (0x88CCL)
1296          * Action: Packet_In to Controller Reserved Port
1297          */
1298
1299          writeLLDPRule(dpid);
1300          if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1301              writeNormalRule(dpid);
1302          }
1303     }
1304
1305     /*
1306     * Create an LLDP Flow Rule to encapsulate into
1307     * a packet_in that is sent to the controller
1308     * for topology handling.
1309     * Match: Ethertype 0x88CCL
1310     * Action: Punt to Controller in a Packet_In msg
1311     */
1312
1313     private void writeLLDPRule(Long dpidLong) {
1314
1315         String nodeName = "openflow:" + dpidLong;
1316         EtherType etherType = new EtherType(0x88CCL);
1317
1318         MatchBuilder matchBuilder = new MatchBuilder();
1319         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1320         FlowBuilder flowBuilder = new FlowBuilder();
1321
1322         // Create Match(es) and Set them in the FlowBuilder Object
1323         flowBuilder.setMatch(createEtherTypeMatch(matchBuilder, etherType).build());
1324
1325         // Create the OF Actions and Instructions
1326         InstructionBuilder ib = new InstructionBuilder();
1327         InstructionsBuilder isb = new InstructionsBuilder();
1328
1329         // Instructions List Stores Individual Instructions
1330         List<Instruction> instructions = Lists.newArrayList();
1331
1332         // Call the InstructionBuilder Methods Containing Actions
1333         createSendToControllerInstructions(ib);
1334         ib.setOrder(0);
1335         ib.setKey(new InstructionKey(0));
1336         instructions.add(ib.build());
1337
1338         // Add InstructionBuilder to the Instruction(s)Builder List
1339         isb.setInstruction(instructions);
1340
1341         // Add InstructionsBuilder to FlowBuilder
1342         flowBuilder.setInstructions(isb.build());
1343
1344         String flowId = "LLDP";
1345         flowBuilder.setId(new FlowId(flowId));
1346         FlowKey key = new FlowKey(new FlowId(flowId));
1347         flowBuilder.setBarrier(true);
1348         flowBuilder.setTableId((short) 0);
1349         flowBuilder.setKey(key);
1350         flowBuilder.setFlowName(flowId);
1351         flowBuilder.setHardTimeout(0);
1352         flowBuilder.setIdleTimeout(0);
1353         writeFlow(flowBuilder, nodeBuilder);
1354     }
1355
1356     /*
1357     * Create a NORMAL Table Miss Flow Rule
1358     * Match: any
1359     * Action: forward to NORMAL pipeline
1360     */
1361
1362     private void writeNormalRule(Long dpidLong) {
1363
1364         String nodeName = "openflow:" + dpidLong;
1365
1366         MatchBuilder matchBuilder = new MatchBuilder();
1367         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1368         FlowBuilder flowBuilder = new FlowBuilder();
1369
1370         // Create the OF Actions and Instructions
1371         InstructionBuilder ib = new InstructionBuilder();
1372         InstructionsBuilder isb = new InstructionsBuilder();
1373
1374         // Instructions List Stores Individual Instructions
1375         List<Instruction> instructions = Lists.newArrayList();
1376
1377         // Call the InstructionBuilder Methods Containing Actions
1378         createNormalInstructions(ib);
1379         ib.setOrder(0);
1380         ib.setKey(new InstructionKey(0));
1381         instructions.add(ib.build());
1382
1383         // Add InstructionBuilder to the Instruction(s)Builder List
1384         isb.setInstruction(instructions);
1385
1386         // Add InstructionsBuilder to FlowBuilder
1387         flowBuilder.setInstructions(isb.build());
1388
1389         String flowId = "NORMAL";
1390         flowBuilder.setId(new FlowId(flowId));
1391         FlowKey key = new FlowKey(new FlowId(flowId));
1392         flowBuilder.setMatch(matchBuilder.build());
1393         flowBuilder.setPriority(0);
1394         flowBuilder.setBarrier(true);
1395         flowBuilder.setTableId((short) 0);
1396         flowBuilder.setKey(key);
1397         flowBuilder.setFlowName(flowId);
1398         flowBuilder.setHardTimeout(0);
1399         flowBuilder.setIdleTimeout(0);
1400         writeFlow(flowBuilder, nodeBuilder);
1401     }
1402
1403     /*
1404      * (Table:0) Ingress Tunnel Traffic
1405      * Match: OpenFlow InPort and Tunnel ID
1406      * Action: GOTO Local Table (10)
1407      * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
1408      */
1409
1410     private void handleTunnelIn(Long dpidLong, Short writeTable,
1411                                 Short goToTableId, String segmentationId,
1412                                 Long ofPort, boolean write) {
1413
1414         String nodeName = "openflow:" + dpidLong;
1415
1416         BigInteger tunnelId = new BigInteger(segmentationId);
1417         MatchBuilder matchBuilder = new MatchBuilder();
1418         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1419         FlowBuilder flowBuilder = new FlowBuilder();
1420
1421         // Create Match(es) and Set them in the FlowBuilder Object
1422         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, tunnelId).build());
1423         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, ofPort).build());
1424
1425         if (write) {
1426             // Create the OF Actions and Instructions
1427             InstructionBuilder ib = new InstructionBuilder();
1428             InstructionsBuilder isb = new InstructionsBuilder();
1429
1430             // Instructions List Stores Individual Instructions
1431             List<Instruction> instructions = Lists.newArrayList();
1432
1433             // Call the InstructionBuilder Methods Containing Actions
1434             createGotoTableInstructions(ib, goToTableId);
1435             ib.setOrder(0);
1436             ib.setKey(new InstructionKey(0));
1437             instructions.add(ib.build());
1438
1439             // Add InstructionBuilder to the Instruction(s)Builder List
1440             isb.setInstruction(instructions);
1441
1442             // Add InstructionsBuilder to FlowBuilder
1443             flowBuilder.setInstructions(isb.build());
1444         }
1445
1446         String flowId = "TunnelIn_"+segmentationId+"_"+ofPort;
1447         // Add Flow Attributes
1448         flowBuilder.setId(new FlowId(flowId));
1449         FlowKey key = new FlowKey(new FlowId(flowId));
1450         flowBuilder.setStrict(true);
1451         flowBuilder.setBarrier(false);
1452         flowBuilder.setTableId(writeTable);
1453         flowBuilder.setKey(key);
1454         flowBuilder.setFlowName(flowId);
1455         flowBuilder.setHardTimeout(0);
1456         flowBuilder.setIdleTimeout(0);
1457
1458         if (write) {
1459             writeFlow(flowBuilder, nodeBuilder);
1460         } else {
1461             removeFlow(flowBuilder, nodeBuilder);
1462         }
1463     }
1464
1465     /*
1466      * (Table:0) Ingress VLAN Traffic
1467      * Match: OpenFlow InPort and vlan ID
1468      * Action: GOTO Local Table (20)
1469      * table=0,vlan_id=0x5,in_port=10, actions=goto_table:2
1470      */
1471
1472     private void handleVlanIn(Long dpidLong, Short writeTable, Short goToTableId,
1473                       String segmentationId,  Long ethPort, boolean write) {
1474
1475         String nodeName = "openflow:" + dpidLong;
1476
1477         MatchBuilder matchBuilder = new MatchBuilder();
1478         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1479         FlowBuilder flowBuilder = new FlowBuilder();
1480
1481         // Create Match(es) and Set them in the FlowBuilder Object
1482         flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
1483         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, ethPort).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 = Lists.newArrayList();
1492
1493             // Call the InstructionBuilder Methods Containing Actions
1494             createGotoTableInstructions(ib, goToTableId);
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 = "VlanIn_"+segmentationId+"_"+ethPort;
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.setFlowName(flowId);
1515         flowBuilder.setHardTimeout(0);
1516         flowBuilder.setIdleTimeout(0);
1517         if (write) {
1518             writeFlow(flowBuilder, nodeBuilder);
1519         } else {
1520             removeFlow(flowBuilder, nodeBuilder);
1521         }
1522     }
1523
1524    /*
1525     * (Table:0) Egress VM Traffic Towards TEP
1526     * Match: Destination Ethernet Addr and OpenFlow InPort
1527     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1528     * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1529     * actions=set_field:5->tun_id,goto_table=1"
1530     */
1531
1532     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
1533                            String segmentationId, Long inPort, String attachedMac,
1534                            boolean write) {
1535
1536         String nodeName = "openflow:" + dpidLong;
1537
1538         MatchBuilder matchBuilder = new MatchBuilder();
1539         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1540         FlowBuilder flowBuilder = new FlowBuilder();
1541
1542         // Create the OF Match using MatchBuilder
1543         flowBuilder.setMatch(createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
1544         // TODO Broken In_Port Match
1545         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
1546
1547         String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
1548         // Add Flow Attributes
1549         flowBuilder.setId(new FlowId(flowId));
1550         FlowKey key = new FlowKey(new FlowId(flowId));
1551         flowBuilder.setStrict(true);
1552         flowBuilder.setBarrier(false);
1553         flowBuilder.setTableId(writeTable);
1554         flowBuilder.setKey(key);
1555         flowBuilder.setFlowName(flowId);
1556         flowBuilder.setHardTimeout(0);
1557         flowBuilder.setIdleTimeout(0);
1558
1559         if (write) {
1560             // Instantiate the Builders for the OF Actions and Instructions
1561             InstructionBuilder ib = new InstructionBuilder();
1562             InstructionsBuilder isb = new InstructionsBuilder();
1563
1564             // Instructions List Stores Individual Instructions
1565             List<Instruction> instructions = Lists.newArrayList();
1566
1567             // GOTO Instuctions Need to be added first to the List
1568             createGotoTableInstructions(ib, goToTableId);
1569             ib.setOrder(0);
1570             ib.setKey(new InstructionKey(0));
1571             instructions.add(ib.build());
1572             // TODO Broken SetTunID
1573             createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
1574             ib.setOrder(1);
1575             ib.setKey(new InstructionKey(1));
1576             instructions.add(ib.build());
1577
1578             // Add InstructionBuilder to the Instruction(s)Builder List
1579             isb.setInstruction(instructions);
1580
1581             // Add InstructionsBuilder to FlowBuilder
1582             flowBuilder.setInstructions(isb.build());
1583
1584             writeFlow(flowBuilder, nodeBuilder);
1585         } else {
1586             removeFlow(flowBuilder, nodeBuilder);
1587         }
1588     }
1589
1590     /*
1591      * (Table:0) Egress VM Traffic Towards TEP
1592      * Match: Source Ethernet Addr and OpenFlow InPort
1593      * Instruction: Set VLANID and GOTO Table Egress (n)
1594      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1595      * actions=push_vlan, set_field:5->vlan_id,goto_table=1"
1596      */
1597
1598      private void handleLocalInPortSetVlan(Long dpidLong, Short writeTable,
1599                                   Short goToTableId, String segmentationId,
1600                                   Long inPort, String attachedMac,
1601                                   boolean write) {
1602
1603          String nodeName = "openflow:" + dpidLong;
1604
1605          MatchBuilder matchBuilder = new MatchBuilder();
1606          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1607          FlowBuilder flowBuilder = new FlowBuilder();
1608
1609          // Create the OF Match using MatchBuilder
1610          flowBuilder.setMatch(createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
1611          // TODO Broken In_Port Match
1612          flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
1613
1614          String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
1615          // Add Flow Attributes
1616          flowBuilder.setId(new FlowId(flowId));
1617          FlowKey key = new FlowKey(new FlowId(flowId));
1618          flowBuilder.setStrict(true);
1619          flowBuilder.setBarrier(false);
1620          flowBuilder.setTableId(writeTable);
1621          flowBuilder.setKey(key);
1622          flowBuilder.setFlowName(flowId);
1623          flowBuilder.setHardTimeout(0);
1624          flowBuilder.setIdleTimeout(0);
1625
1626          if (write) {
1627              // Instantiate the Builders for the OF Actions and Instructions
1628              InstructionBuilder ib = new InstructionBuilder();
1629              InstructionsBuilder isb = new InstructionsBuilder();
1630
1631              // Instructions List Stores Individual Instructions
1632              List<Instruction> instructions = Lists.newArrayList();
1633
1634              // GOTO Instructions Need to be added first to the List
1635              createGotoTableInstructions(ib, goToTableId);
1636              ib.setOrder(0);
1637              ib.setKey(new InstructionKey(0));
1638              instructions.add(ib.build());
1639              // Set VLAN ID Instruction
1640              createSetVlanInstructions(ib, new VlanId(Integer.valueOf(segmentationId)));
1641              ib.setOrder(1);
1642              ib.setKey(new InstructionKey(1));
1643              instructions.add(ib.build());
1644
1645              // Add InstructionBuilder to the Instruction(s)Builder List
1646              isb.setInstruction(instructions);
1647
1648              // Add InstructionsBuilder to FlowBuilder
1649              flowBuilder.setInstructions(isb.build());
1650
1651              writeFlow(flowBuilder, nodeBuilder);
1652          } else {
1653              removeFlow(flowBuilder, nodeBuilder);
1654          }
1655      }
1656
1657     /*
1658      * (Table:0) Drop frames source from a VM that do not
1659      * match the associated MAC address of the local VM.
1660      * Match: Low priority anything not matching the VM SMAC
1661      * Instruction: Drop
1662      * table=0,priority=16384,in_port=1 actions=drop"
1663      */
1664
1665     private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
1666
1667         String nodeName = "openflow:" + dpidLong;
1668
1669         MatchBuilder matchBuilder = new MatchBuilder();
1670         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1671         FlowBuilder flowBuilder = new FlowBuilder();
1672
1673         // Create the OF Match using MatchBuilder
1674         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
1675
1676         if (write) {
1677             // Instantiate the Builders for the OF Actions and Instructions
1678             InstructionBuilder ib = new InstructionBuilder();
1679             InstructionsBuilder isb = new InstructionsBuilder();
1680
1681             // Instructions List Stores Individual Instructions
1682             List<Instruction> instructions = Lists.newArrayList();
1683
1684             // Call the InstructionBuilder Methods Containing Actions
1685             createDropInstructions(ib);
1686             ib.setOrder(0);
1687             ib.setKey(new InstructionKey(0));
1688             instructions.add(ib.build());
1689
1690             // Add InstructionBuilder to the Instruction(s)Builder List
1691             isb.setInstruction(instructions);
1692
1693             // Add InstructionsBuilder to FlowBuilder
1694             flowBuilder.setInstructions(isb.build());
1695         }
1696
1697         String flowId = "DropFilter_"+inPort;
1698         // Add Flow Attributes
1699         flowBuilder.setId(new FlowId(flowId));
1700         FlowKey key = new FlowKey(new FlowId(flowId));
1701         flowBuilder.setStrict(true);
1702         flowBuilder.setBarrier(false);
1703         flowBuilder.setTableId((short) 0);
1704         flowBuilder.setKey(key);
1705         flowBuilder.setFlowName(flowId);
1706         flowBuilder.setPriority(8192);
1707         flowBuilder.setHardTimeout(0);
1708         flowBuilder.setIdleTimeout(0);
1709         if (write) {
1710             writeFlow(flowBuilder, nodeBuilder);
1711         } else {
1712             removeFlow(flowBuilder, nodeBuilder);
1713         }
1714     }
1715
1716    /*
1717     * (Table:1) Egress Tunnel Traffic
1718     * Match: Destination Ethernet Addr and Local InPort
1719     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1720     * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
1721     * actions=output:10,goto_table:2"
1722     */
1723     private void handleTunnelOut(Long dpidLong, Short writeTable,
1724                          Short goToTableId, String segmentationId,
1725                          Long OFPortOut, String attachedMac,
1726                          boolean write) {
1727
1728         String nodeName = "openflow:" + dpidLong;
1729
1730         MatchBuilder matchBuilder = new MatchBuilder();
1731         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1732         FlowBuilder flowBuilder = new FlowBuilder();
1733
1734         // Create the OF Match using MatchBuilder
1735         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1736         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
1737
1738         String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
1739         // Add Flow Attributes
1740         flowBuilder.setId(new FlowId(flowId));
1741         FlowKey key = new FlowKey(new FlowId(flowId));
1742         flowBuilder.setStrict(true);
1743         flowBuilder.setBarrier(false);
1744         flowBuilder.setTableId(writeTable);
1745         flowBuilder.setKey(key);
1746         flowBuilder.setFlowName(flowId);
1747         flowBuilder.setHardTimeout(0);
1748         flowBuilder.setIdleTimeout(0);
1749
1750         if (write) {
1751             // Instantiate the Builders for the OF Actions and Instructions
1752             InstructionBuilder ib = new InstructionBuilder();
1753             InstructionsBuilder isb = new InstructionsBuilder();
1754
1755             // Instructions List Stores Individual Instructions
1756             List<Instruction> instructions = Lists.newArrayList();
1757
1758             // GOTO Instuctions
1759             createGotoTableInstructions(ib, goToTableId);
1760             ib.setOrder(0);
1761             ib.setKey(new InstructionKey(0));
1762             instructions.add(ib.build());
1763             // Set the Output Port/Iface
1764             createOutputPortInstructions(ib, dpidLong, OFPortOut);
1765             ib.setOrder(1);
1766             ib.setKey(new InstructionKey(1));
1767             instructions.add(ib.build());
1768
1769             // Add InstructionBuilder to the Instruction(s)Builder List
1770             isb.setInstruction(instructions);
1771
1772             // Add InstructionsBuilder to FlowBuilder
1773             flowBuilder.setInstructions(isb.build());
1774
1775             writeFlow(flowBuilder, nodeBuilder);
1776         } else {
1777             removeFlow(flowBuilder, nodeBuilder);
1778         }
1779     }
1780
1781     /*
1782      * (Table:1) Egress VLAN Traffic
1783      * Match: Destination Ethernet Addr and VLAN id
1784      * Instruction: GOTO Table Table 2
1785      * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
1786      * actions= goto_table:2"
1787      */
1788
1789      private void handleVlanOut(Long dpidLong, Short writeTable,
1790                         Short goToTableId, String segmentationId,
1791                         Long ethPort, String attachedMac, boolean write) {
1792
1793          String nodeName = "openflow:" + dpidLong;
1794
1795          MatchBuilder matchBuilder = new MatchBuilder();
1796          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1797          FlowBuilder flowBuilder = new FlowBuilder();
1798
1799          // Create the OF Match using MatchBuilder
1800          flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
1801          flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
1802
1803          String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
1804          // Add Flow Attributes
1805          flowBuilder.setId(new FlowId(flowId));
1806          FlowKey key = new FlowKey(new FlowId(flowId));
1807          flowBuilder.setStrict(true);
1808          flowBuilder.setBarrier(false);
1809          flowBuilder.setTableId(writeTable);
1810          flowBuilder.setKey(key);
1811          flowBuilder.setFlowName(flowId);
1812          flowBuilder.setHardTimeout(0);
1813          flowBuilder.setIdleTimeout(0);
1814
1815          if (write) {
1816              // Instantiate the Builders for the OF Actions and Instructions
1817              InstructionBuilder ib = new InstructionBuilder();
1818              InstructionsBuilder isb = new InstructionsBuilder();
1819
1820              // Instructions List Stores Individual Instructions
1821              List<Instruction> instructions = Lists.newArrayList();
1822
1823              // GOTO Instuctions
1824              createGotoTableInstructions(ib, goToTableId);
1825              ib.setOrder(0);
1826              ib.setKey(new InstructionKey(0));
1827              instructions.add(ib.build());
1828
1829              // Add InstructionBuilder to the Instruction(s)Builder List
1830              isb.setInstruction(instructions);
1831
1832              // Add InstructionsBuilder to FlowBuilder
1833              flowBuilder.setInstructions(isb.build());
1834
1835              writeFlow(flowBuilder, nodeBuilder);
1836          } else {
1837              removeFlow(flowBuilder, nodeBuilder);
1838          }
1839      }
1840
1841        /*
1842     * (Table:1) Egress Tunnel Traffic
1843     * Match: Destination Ethernet Addr and Local InPort
1844     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1845     * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1846     * actions=output:10,output:11,goto_table:2
1847     */
1848
1849     private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
1850                              Short localTable, String segmentationId,
1851                              Long OFPortOut, boolean write) {
1852
1853         String nodeName = "openflow:" + dpidLong;
1854
1855         MatchBuilder matchBuilder = new MatchBuilder();
1856         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1857         FlowBuilder flowBuilder = new FlowBuilder();
1858
1859         // Create the OF Match using MatchBuilder
1860         // Match TunnelID
1861         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
1862         // Match DMAC
1863
1864         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
1865
1866         String flowId = "TunnelFloodOut_"+segmentationId;
1867         // Add Flow Attributes
1868         flowBuilder.setId(new FlowId(flowId));
1869         FlowKey key = new FlowKey(new FlowId(flowId));
1870         flowBuilder.setBarrier(true);
1871         flowBuilder.setTableId(writeTable);
1872         flowBuilder.setKey(key);
1873         flowBuilder.setPriority(16384);
1874         flowBuilder.setFlowName(flowId);
1875         flowBuilder.setHardTimeout(0);
1876         flowBuilder.setIdleTimeout(0);
1877
1878         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
1879         // Instantiate the Builders for the OF Actions and Instructions
1880         InstructionBuilder ib = new InstructionBuilder();
1881         InstructionsBuilder isb = new InstructionsBuilder();
1882         List<Instruction> instructions = Lists.newArrayList();
1883         List<Instruction> existingInstructions = null;
1884         if (flow != null) {
1885             Instructions ins = flow.getInstructions();
1886             if (ins != null) {
1887                 existingInstructions = ins.getInstruction();
1888             }
1889         }
1890
1891         if (write) {
1892             // GOTO Instruction
1893             createGotoTableInstructions(ib, localTable);
1894             ib.setOrder(0);
1895             ib.setKey(new InstructionKey(0));
1896             instructions.add(ib.build());
1897             // Set the Output Port/Iface
1898             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
1899             createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
1900             ib.setOrder(1);
1901             ib.setKey(new InstructionKey(1));
1902             instructions.add(ib.build());
1903
1904             // Add InstructionBuilder to the Instruction(s)Builder List
1905             isb.setInstruction(instructions);
1906
1907             // Add InstructionsBuilder to FlowBuilder
1908             flowBuilder.setInstructions(isb.build());
1909
1910             writeFlow(flowBuilder, nodeBuilder);
1911         } else {
1912             /* remove port from action list */
1913             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
1914                                    OFPortOut, existingInstructions);
1915             if (flowRemove) {
1916                 /* if all port are removed, remove the flow too. */
1917                 removeFlow(flowBuilder, nodeBuilder);
1918             } else {
1919                 /* Install instruction with new output port list*/
1920                 ib.setOrder(0);
1921                 ib.setKey(new InstructionKey(0));
1922                 instructions.add(ib.build());
1923
1924                 // Add InstructionBuilder to the Instruction(s)Builder List
1925                 isb.setInstruction(instructions);
1926
1927                 // Add InstructionsBuilder to FlowBuilder
1928                 flowBuilder.setInstructions(isb.build());
1929             }
1930         }
1931     }
1932
1933     /*
1934      * (Table:1) Egress VLAN Traffic
1935      * Match: Destination Ethernet Addr and VLAN id
1936      * Instruction: GOTO table 2 and Output port eth interface
1937      * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1938      * actions=output:eth1,goto_table:2
1939      */
1940
1941      private void handleVlanFloodOut(Long dpidLong, Short writeTable,
1942                            Short localTable, String segmentationId,
1943                            Long ethPort, boolean write) {
1944
1945          String nodeName = "openflow:" + dpidLong;
1946
1947          MatchBuilder matchBuilder = new MatchBuilder();
1948          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
1949          FlowBuilder flowBuilder = new FlowBuilder();
1950
1951          // Create the OF Match using MatchBuilder
1952          // Match Vlan ID
1953          flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
1954          // Match DMAC
1955          flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
1956
1957          String flowId = "VlanFloodOut_"+segmentationId;
1958          // Add Flow Attributes
1959          flowBuilder.setId(new FlowId(flowId));
1960          FlowKey key = new FlowKey(new FlowId(flowId));
1961          flowBuilder.setBarrier(true);
1962          flowBuilder.setTableId(writeTable);
1963          flowBuilder.setKey(key);
1964          flowBuilder.setPriority(16384);
1965          flowBuilder.setFlowName(flowId);
1966          flowBuilder.setHardTimeout(0);
1967          flowBuilder.setIdleTimeout(0);
1968
1969          //ToDo: Is there something to be done with result of the call to getFlow?
1970
1971          Flow flow = this.getFlow(flowBuilder, nodeBuilder);
1972          // Instantiate the Builders for the OF Actions and Instructions
1973          InstructionBuilder ib = new InstructionBuilder();
1974          InstructionsBuilder isb = new InstructionsBuilder();
1975          List<Instruction> instructions = Lists.newArrayList();
1976
1977          if (write) {
1978              // GOTO Instuction
1979              createGotoTableInstructions(ib, localTable);
1980              ib.setOrder(0);
1981              ib.setKey(new InstructionKey(0));
1982              instructions.add(ib.build());
1983              // Set the Output Port/Iface
1984              createOutputPortInstructions(ib, dpidLong, ethPort);
1985              ib.setOrder(1);
1986              ib.setKey(new InstructionKey(1));
1987              instructions.add(ib.build());
1988
1989              // Add InstructionBuilder to the Instruction(s)Builder List
1990              isb.setInstruction(instructions);
1991
1992              // Add InstructionsBuilder to FlowBuilder
1993              flowBuilder.setInstructions(isb.build());
1994
1995              writeFlow(flowBuilder, nodeBuilder);
1996          } else {
1997              removeFlow(flowBuilder, nodeBuilder);
1998          }
1999      }
2000
2001    /*
2002     * (Table:1) Table Drain w/ Catch All
2003     * Match: Tunnel ID
2004     * Action: GOTO Local Table (10)
2005     * table=2,priority=8192,tun_id=0x5 actions=drop
2006     */
2007
2008     private void handleTunnelMiss(Long dpidLong, Short writeTable,
2009                           Short goToTableId, String segmentationId,
2010                           boolean write) {
2011
2012         String nodeName = "openflow:" + dpidLong;
2013
2014         MatchBuilder matchBuilder = new MatchBuilder();
2015         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2016         FlowBuilder flowBuilder = new FlowBuilder();
2017
2018         // Create Match(es) and Set them in the FlowBuilder Object
2019         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2020
2021         if (write) {
2022             // Create the OF Actions and Instructions
2023             InstructionBuilder ib = new InstructionBuilder();
2024             InstructionsBuilder isb = new InstructionsBuilder();
2025
2026             // Instructions List Stores Individual Instructions
2027             List<Instruction> instructions = Lists.newArrayList();
2028
2029             // Call the InstructionBuilder Methods Containing Actions
2030             createGotoTableInstructions(ib, goToTableId);
2031             ib.setOrder(0);
2032             ib.setKey(new InstructionKey(0));
2033             instructions.add(ib.build());
2034
2035             // Add InstructionBuilder to the Instruction(s)Builder List
2036             isb.setInstruction(instructions);
2037
2038             // Add InstructionsBuilder to FlowBuilder
2039             flowBuilder.setInstructions(isb.build());
2040         }
2041
2042         String flowId = "TunnelMiss_"+segmentationId;
2043         // Add Flow Attributes
2044         flowBuilder.setId(new FlowId(flowId));
2045         FlowKey key = new FlowKey(new FlowId(flowId));
2046         flowBuilder.setStrict(true);
2047         flowBuilder.setBarrier(false);
2048         flowBuilder.setTableId(writeTable);
2049         flowBuilder.setKey(key);
2050         flowBuilder.setPriority(8192);
2051         flowBuilder.setFlowName(flowId);
2052         flowBuilder.setHardTimeout(0);
2053         flowBuilder.setIdleTimeout(0);
2054         if (write) {
2055             writeFlow(flowBuilder, nodeBuilder);
2056         } else {
2057             removeFlow(flowBuilder, nodeBuilder);
2058         }
2059     }
2060
2061
2062     /*
2063      * (Table:1) Table Drain w/ Catch All
2064      * Match: Vlan ID
2065      * Action: Output port eth interface
2066      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
2067      */
2068
2069      private void handleVlanMiss(Long dpidLong, Short writeTable,
2070                          Short goToTableId, String segmentationId,
2071                          Long ethPort, boolean write) {
2072
2073          String nodeName = "openflow:" + dpidLong;
2074
2075          MatchBuilder matchBuilder = new MatchBuilder();
2076          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2077          FlowBuilder flowBuilder = new FlowBuilder();
2078
2079          // Create Match(es) and Set them in the FlowBuilder Object
2080          flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2081
2082          if (write) {
2083              // Create the OF Actions and Instructions
2084              InstructionBuilder ib = new InstructionBuilder();
2085              InstructionsBuilder isb = new InstructionsBuilder();
2086
2087              // Instructions List Stores Individual Instructions
2088              List<Instruction> instructions = Lists.newArrayList();
2089
2090              // Call the InstructionBuilder Methods Containing Actions
2091              //createGotoTableInstructions(ib, goToTableId);
2092              //ib.setOrder(0);
2093              //ib.setKey(new InstructionKey(0));
2094              //instructions.add(ib.build());
2095              // Set the Output Port/Iface
2096              createOutputPortInstructions(ib, dpidLong, ethPort);
2097              ib.setOrder(0);
2098              ib.setKey(new InstructionKey(1));
2099              instructions.add(ib.build());
2100
2101              // Add InstructionBuilder to the Instruction(s)Builder List
2102              isb.setInstruction(instructions);
2103
2104              // Add InstructionsBuilder to FlowBuilder
2105              flowBuilder.setInstructions(isb.build());
2106          }
2107
2108          String flowId = "VlanMiss_"+segmentationId;
2109          // Add Flow Attributes
2110          flowBuilder.setId(new FlowId(flowId));
2111          FlowKey key = new FlowKey(new FlowId(flowId));
2112          flowBuilder.setStrict(true);
2113          flowBuilder.setBarrier(false);
2114          flowBuilder.setTableId(writeTable);
2115          flowBuilder.setKey(key);
2116          flowBuilder.setPriority(8192);
2117          flowBuilder.setFlowName(flowId);
2118          flowBuilder.setHardTimeout(0);
2119          flowBuilder.setIdleTimeout(0);
2120          if (write) {
2121              writeFlow(flowBuilder, nodeBuilder);
2122          } else {
2123              removeFlow(flowBuilder, nodeBuilder);
2124          }
2125      }
2126
2127     /*
2128      * (Table:1) Local Broadcast Flood
2129      * Match: Tunnel ID and dMAC
2130      * Action: Output Port
2131      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
2132      */
2133
2134     private void handleLocalUcastOut(Long dpidLong, Short writeTable,
2135                              String segmentationId, Long localPort,
2136                              String attachedMac, boolean write) {
2137
2138         String nodeName = "openflow:" + dpidLong;
2139
2140         MatchBuilder matchBuilder = new MatchBuilder();
2141         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2142         FlowBuilder flowBuilder = new FlowBuilder();
2143
2144         // Create the OF Match using MatchBuilder
2145         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2146         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
2147
2148         String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
2149         // Add Flow Attributes
2150         flowBuilder.setId(new FlowId(flowId));
2151         FlowKey key = new FlowKey(new FlowId(flowId));
2152         flowBuilder.setStrict(true);
2153         flowBuilder.setBarrier(false);
2154         flowBuilder.setTableId(writeTable);
2155         flowBuilder.setKey(key);
2156         flowBuilder.setFlowName(flowId);
2157         flowBuilder.setHardTimeout(0);
2158         flowBuilder.setIdleTimeout(0);
2159
2160         if (write) {
2161             // Instantiate the Builders for the OF Actions and Instructions
2162             InstructionBuilder ib = new InstructionBuilder();
2163             InstructionsBuilder isb = new InstructionsBuilder();
2164
2165             // Instructions List Stores Individual Instructions
2166             List<Instruction> instructions = Lists.newArrayList();
2167
2168             // Set the Output Port/Iface
2169             createOutputPortInstructions(ib, dpidLong, localPort);
2170             ib.setOrder(0);
2171             ib.setKey(new InstructionKey(0));
2172             instructions.add(ib.build());
2173
2174             // Add InstructionBuilder to the Instruction(s)Builder List
2175             isb.setInstruction(instructions);
2176
2177             // Add InstructionsBuilder to FlowBuilder
2178             flowBuilder.setInstructions(isb.build());
2179             writeFlow(flowBuilder, nodeBuilder);
2180         } else {
2181             removeFlow(flowBuilder, nodeBuilder);
2182         }
2183     }
2184
2185     /*
2186      * (Table:2) Local VLAN unicast
2187      * Match: VLAN ID and dMAC
2188      * Action: Output Port
2189      * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
2190      */
2191
2192     private void handleLocalVlanUcastOut(Long dpidLong, Short writeTable,
2193                                  String segmentationId, Long localPort,
2194                                  String attachedMac, boolean write) {
2195
2196         String nodeName = "openflow:" + dpidLong;
2197
2198         MatchBuilder matchBuilder = new MatchBuilder();
2199         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2200         FlowBuilder flowBuilder = new FlowBuilder();
2201
2202         // Create the OF Match using MatchBuilder
2203         flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2204         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
2205
2206         String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
2207         // Add Flow Attributes
2208         flowBuilder.setId(new FlowId(flowId));
2209         FlowKey key = new FlowKey(new FlowId(flowId));
2210         flowBuilder.setStrict(true);
2211         flowBuilder.setBarrier(false);
2212         flowBuilder.setTableId(writeTable);
2213         flowBuilder.setKey(key);
2214         flowBuilder.setFlowName(flowId);
2215         flowBuilder.setHardTimeout(0);
2216         flowBuilder.setIdleTimeout(0);
2217
2218         if (write) {
2219             // Instantiate the Builders for the OF Actions and Instructions
2220             InstructionBuilder ib = new InstructionBuilder();
2221             InstructionsBuilder isb = new InstructionsBuilder();
2222
2223             // Instructions List Stores Individual Instructions
2224             List<Instruction> instructions = Lists.newArrayList();
2225             List<Instruction> instructions_tmp = Lists.newArrayList();
2226
2227             /* Strip vlan and store to tmp instruction space*/
2228             createPopVlanInstructions(ib);
2229             ib.setOrder(0);
2230             ib.setKey(new InstructionKey(0));
2231             instructions_tmp.add(ib.build());
2232
2233             // Set the Output Port/Iface
2234             ib = new InstructionBuilder();
2235             addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
2236             ib.setOrder(0);
2237             ib.setKey(new InstructionKey(0));
2238             instructions.add(ib.build());
2239
2240             // Add InstructionBuilder to the Instruction(s)Builder List
2241             isb.setInstruction(instructions);
2242
2243             // Add InstructionsBuilder to FlowBuilder
2244             flowBuilder.setInstructions(isb.build());
2245             writeFlow(flowBuilder, nodeBuilder);
2246         } else {
2247             removeFlow(flowBuilder, nodeBuilder);
2248         }
2249     }
2250
2251     /*
2252      * (Table:2) Local Broadcast Flood
2253      * Match: Tunnel ID and dMAC (::::FF:FF)
2254      * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
2255      * actions=output:2,3,4,5
2256      */
2257
2258     private void handleLocalBcastOut(Long dpidLong, Short writeTable,
2259                              String segmentationId, Long localPort,
2260                              boolean write) {
2261
2262         String nodeName = "openflow:" + dpidLong;
2263
2264         MatchBuilder matchBuilder = new MatchBuilder();
2265         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2266         FlowBuilder flowBuilder = new FlowBuilder();
2267
2268         // Create the OF Match using MatchBuilder
2269         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2270         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
2271
2272         String flowId = "BcastOut_"+segmentationId;
2273         // Add Flow Attributes
2274         flowBuilder.setId(new FlowId(flowId));
2275         FlowKey key = new FlowKey(new FlowId(flowId));
2276         flowBuilder.setStrict(true);
2277         flowBuilder.setBarrier(false);
2278         flowBuilder.setTableId(writeTable);
2279         flowBuilder.setKey(key);
2280         flowBuilder.setPriority(16384);
2281         flowBuilder.setFlowName(flowId);
2282         flowBuilder.setHardTimeout(0);
2283         flowBuilder.setIdleTimeout(0);
2284         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
2285         // Instantiate the Builders for the OF Actions and Instructions
2286         InstructionBuilder ib = new InstructionBuilder();
2287         InstructionsBuilder isb = new InstructionsBuilder();
2288         List<Instruction> instructions = Lists.newArrayList();
2289         List<Instruction> existingInstructions = null;
2290         if (flow != null) {
2291             Instructions ins = flow.getInstructions();
2292             if (ins != null) {
2293                 existingInstructions = ins.getInstruction();
2294             }
2295         }
2296
2297         if (write) {
2298             // Create output port list
2299             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
2300             ib.setOrder(0);
2301             ib.setKey(new InstructionKey(0));
2302             instructions.add(ib.build());
2303
2304             // Add InstructionBuilder to the Instruction(s)Builder List
2305             isb.setInstruction(instructions);
2306
2307             // Add InstructionsBuilder to FlowBuilder
2308             flowBuilder.setInstructions(isb.build());
2309
2310             writeFlow(flowBuilder, nodeBuilder);
2311         } else {
2312             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort,
2313                                                                   existingInstructions);
2314             if (flowRemove) {
2315                 /* if all ports are removed, remove flow */
2316                 removeFlow(flowBuilder, nodeBuilder);
2317             } else {
2318                 /* Install instruction with new output port list*/
2319                 ib.setOrder(0);
2320                 ib.setKey(new InstructionKey(0));
2321                 instructions.add(ib.build());
2322
2323                 // Add InstructionBuilder to the Instruction(s)Builder List
2324                 isb.setInstruction(instructions);
2325
2326                 // Add InstructionsBuilder to FlowBuilder
2327                 flowBuilder.setInstructions(isb.build());
2328
2329                 writeFlow(flowBuilder, nodeBuilder);
2330             }
2331         }
2332     }
2333
2334     /*
2335      * (Table:2) Local VLAN Broadcast Flood
2336      * Match: vlan ID and dMAC (::::FF:FF)
2337      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
2338      * actions=strip_vlan, output:2,3,4,5
2339      */
2340
2341     private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable,
2342                                  String segmentationId, Long localPort,
2343                                  boolean write) {
2344
2345         String nodeName = "openflow:" + dpidLong;
2346
2347         MatchBuilder matchBuilder = new MatchBuilder();
2348         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2349         FlowBuilder flowBuilder = new FlowBuilder();
2350
2351         // Create the OF Match using MatchBuilder
2352         flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2353         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
2354
2355         String flowId = "VlanBcastOut_"+segmentationId;
2356         // Add Flow Attributes
2357         flowBuilder.setId(new FlowId(flowId));
2358         FlowKey key = new FlowKey(new FlowId(flowId));
2359         flowBuilder.setStrict(true);
2360         flowBuilder.setBarrier(false);
2361         flowBuilder.setTableId(writeTable);
2362         flowBuilder.setKey(key);
2363         flowBuilder.setPriority(16384);
2364         flowBuilder.setFlowName(flowId);
2365         flowBuilder.setHardTimeout(0);
2366         flowBuilder.setIdleTimeout(0);
2367         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
2368         // Instantiate the Builders for the OF Actions and Instructions
2369         InstructionBuilder ib = new InstructionBuilder();
2370         InstructionsBuilder isb = new InstructionsBuilder();
2371         List<Instruction> instructions = Lists.newArrayList();
2372         List<Instruction> existingInstructions = null;
2373         boolean add_pop_vlan = true;
2374         if (flow != null) {
2375             Instructions ins = flow.getInstructions();
2376             if (ins != null) {
2377                 existingInstructions = ins.getInstruction();
2378             }
2379         }
2380
2381         if (write) {
2382             if (existingInstructions != null) {
2383                 /* Check if pop vlan is already the first action in action list */
2384                 List<Action> existingActions;
2385                 for (Instruction in : existingInstructions) {
2386                     if (in.getInstruction() instanceof ApplyActionsCase) {
2387                         existingActions = (((ApplyActionsCase)
2388                                 in.getInstruction()).getApplyActions().getAction());
2389                         if (existingActions.get(0).getAction() instanceof PopVlanActionCase) {
2390                             add_pop_vlan = false;
2391                             break;
2392                         }
2393                     }
2394                 }
2395             } else {
2396                 existingInstructions = Lists.newArrayList();
2397             }
2398
2399             if (add_pop_vlan) {
2400                 /* pop vlan */
2401                 createPopVlanInstructions(ib);
2402                 ib.setOrder(0);
2403                 ib.setKey(new InstructionKey(0));
2404                 existingInstructions.add(ib.build());
2405                 ib = new InstructionBuilder();
2406             }
2407
2408             // Create port list
2409             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, localPort, existingInstructions);
2410             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
2411             ib.setOrder(0);
2412             ib.setKey(new InstructionKey(0));
2413             instructions.add(ib.build());
2414
2415             // Add InstructionBuilder to the Instruction(s)Builder List
2416             isb.setInstruction(instructions);
2417
2418             // Add InstructionsBuilder to FlowBuilder
2419             flowBuilder.setInstructions(isb.build());
2420
2421             writeFlow(flowBuilder, nodeBuilder);
2422         } else {
2423             //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
2424             //                     localPort, existingInstructions);
2425             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
2426                                                     localPort, existingInstructions);
2427             if (flowRemove) {
2428                 /* if all ports are removed, remove flow */
2429                 removeFlow(flowBuilder, nodeBuilder);
2430             } else {
2431                 /* Install instruction with new output port list*/
2432                 ib.setOrder(0);
2433                 ib.setKey(new InstructionKey(0));
2434                 instructions.add(ib.build());
2435
2436                 // Add InstructionBuilder to the Instruction(s)Builder List
2437                 isb.setInstruction(instructions);
2438
2439                 // Add InstructionsBuilder to FlowBuilder
2440                 flowBuilder.setInstructions(isb.build());
2441                 writeFlow(flowBuilder, nodeBuilder);
2442             }
2443         }
2444     }
2445
2446     /*
2447      * (Table:1) Local Table Miss
2448      * Match: Any Remaining Flows w/a TunID
2449      * Action: Drop w/ a low priority
2450      * table=2,priority=8192,tun_id=0x5 actions=drop
2451      */
2452
2453     private void handleLocalTableMiss(Long dpidLong, Short writeTable,
2454                              String segmentationId, boolean write) {
2455
2456         String nodeName = "openflow:" + dpidLong;
2457
2458         MatchBuilder matchBuilder = new MatchBuilder();
2459         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2460         FlowBuilder flowBuilder = new FlowBuilder();
2461
2462         // Create Match(es) and Set them in the FlowBuilder Object
2463         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
2464
2465         if (write) {
2466             // Create the OF Actions and Instructions
2467             InstructionBuilder ib = new InstructionBuilder();
2468             InstructionsBuilder isb = new InstructionsBuilder();
2469
2470             // Instructions List Stores Individual Instructions
2471             List<Instruction> instructions = Lists.newArrayList();
2472
2473             // Call the InstructionBuilder Methods Containing Actions
2474             createDropInstructions(ib);
2475             ib.setOrder(0);
2476             ib.setKey(new InstructionKey(0));
2477             instructions.add(ib.build());
2478
2479             // Add InstructionBuilder to the Instruction(s)Builder List
2480             isb.setInstruction(instructions);
2481
2482             // Add InstructionsBuilder to FlowBuilder
2483             flowBuilder.setInstructions(isb.build());
2484         }
2485
2486         String flowId = "LocalTableMiss_"+segmentationId;
2487         // Add Flow Attributes
2488         flowBuilder.setId(new FlowId(flowId));
2489         FlowKey key = new FlowKey(new FlowId(flowId));
2490         flowBuilder.setStrict(true);
2491         flowBuilder.setBarrier(false);
2492         flowBuilder.setTableId(writeTable);
2493         flowBuilder.setKey(key);
2494         flowBuilder.setPriority(8192);
2495         flowBuilder.setFlowName(flowId);
2496         flowBuilder.setHardTimeout(0);
2497         flowBuilder.setIdleTimeout(0);
2498         if (write) {
2499             writeFlow(flowBuilder, nodeBuilder);
2500         } else {
2501             removeFlow(flowBuilder, nodeBuilder);
2502         }
2503     }
2504
2505     /*
2506      * (Table:1) Local Table Miss
2507      * Match: Any Remaining Flows w/a VLAN ID
2508      * Action: Drop w/ a low priority
2509      * table=2,priority=8192,vlan_id=0x5 actions=drop
2510      */
2511
2512     private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
2513                                   String segmentationId, boolean write) {
2514
2515         String nodeName = "openflow:" + dpidLong;
2516
2517         MatchBuilder matchBuilder = new MatchBuilder();
2518         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
2519         FlowBuilder flowBuilder = new FlowBuilder();
2520
2521         // Create Match(es) and Set them in the FlowBuilder Object
2522         flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
2523
2524         if (write) {
2525             // Create the OF Actions and Instructions
2526             InstructionBuilder ib = new InstructionBuilder();
2527             InstructionsBuilder isb = new InstructionsBuilder();
2528
2529             // Instructions List Stores Individual Instructions
2530             List<Instruction> instructions = Lists.newArrayList();
2531
2532             // Call the InstructionBuilder Methods Containing Actions
2533             createDropInstructions(ib);
2534             ib.setOrder(0);
2535             ib.setKey(new InstructionKey(0));
2536             instructions.add(ib.build());
2537
2538             // Add InstructionBuilder to the Instruction(s)Builder List
2539             isb.setInstruction(instructions);
2540
2541             // Add InstructionsBuilder to FlowBuilder
2542             flowBuilder.setInstructions(isb.build());
2543         }
2544
2545         String flowId = "LocalTableMiss_"+segmentationId;
2546         // Add Flow Attributes
2547         flowBuilder.setId(new FlowId(flowId));
2548         FlowKey key = new FlowKey(new FlowId(flowId));
2549         flowBuilder.setStrict(true);
2550         flowBuilder.setBarrier(false);
2551         flowBuilder.setTableId(writeTable);
2552         flowBuilder.setKey(key);
2553         flowBuilder.setPriority(8192);
2554         flowBuilder.setFlowName(flowId);
2555         flowBuilder.setHardTimeout(0);
2556         flowBuilder.setIdleTimeout(0);
2557         if (write) {
2558             writeFlow(flowBuilder, nodeBuilder);
2559         } else {
2560             removeFlow(flowBuilder, nodeBuilder);
2561         }
2562     }
2563
2564     private Group getGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
2565         Preconditions.checkNotNull(mdsalConsumer);
2566         if (mdsalConsumer == null) {
2567             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2568             return null;
2569         }
2570
2571         dataBroker = mdsalConsumer.getDataBroker();
2572         if (dataBroker == null) {
2573             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2574             return null;
2575         }
2576
2577         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2578                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
2579                 new GroupKey(groupBuilder.getGroupId())).build();
2580         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
2581         try {
2582             Optional<Group> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
2583             if (data.isPresent()) {
2584                 return data.get();
2585             }
2586         } catch (InterruptedException|ExecutionException e) {
2587             logger.error(e.getMessage(), e);
2588         }
2589
2590         logger.debug("Cannot find data for Group " + groupBuilder.getGroupName());
2591         return null;
2592     }
2593
2594     private void writeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
2595         Preconditions.checkNotNull(mdsalConsumer);
2596         if (mdsalConsumer == null) {
2597             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2598             return;
2599         }
2600
2601         dataBroker = mdsalConsumer.getDataBroker();
2602         if (dataBroker == null) {
2603             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2604             return;
2605         }
2606
2607         ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
2608
2609         // Sanity check: do not create parent's tree deeper than we should
2610         InstanceIdentifier<?> requiredPath = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2611                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).build();
2612         try {
2613             if (!modification.read(LogicalDatastoreType.CONFIGURATION, requiredPath).get().isPresent()) {
2614                 logger.error("Unable to get configuration resource to store group "+groupBuilder.getGroupName()
2615                         +" ("+requiredPath.toString()+")");
2616                 return;
2617             }
2618         } catch (InterruptedException|ExecutionException e) {
2619             logger.error(e.getMessage(), e);
2620             return;
2621         }
2622
2623         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2624                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
2625                 new GroupKey(groupBuilder.getGroupId())).build();
2626         modification.put(LogicalDatastoreType.CONFIGURATION, path1, groupBuilder.build(), true /*createMissingParents*/);
2627
2628         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2629         try {
2630             commitFuture.get();  // TODO: Make it async (See bug 1362)
2631             logger.debug("Transaction success for write of Group "+groupBuilder.getGroupName());
2632         } catch (InterruptedException|ExecutionException e) {
2633             logger.error(e.getMessage(), e);
2634         }
2635     }
2636
2637     private void removeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
2638         Preconditions.checkNotNull(mdsalConsumer);
2639         if (mdsalConsumer == null) {
2640             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2641             return;
2642         }
2643
2644         dataBroker = mdsalConsumer.getDataBroker();
2645         if (dataBroker == null) {
2646             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2647             return;
2648         }
2649
2650         WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
2651         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2652                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
2653                 new GroupKey(groupBuilder.getGroupId())).build();
2654         modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
2655         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2656
2657         try {
2658             commitFuture.get();  // TODO: Make it async (See bug 1362)
2659             logger.debug("Transaction success for deletion of Group "+groupBuilder.getGroupName());
2660         } catch (InterruptedException|ExecutionException e) {
2661             logger.error(e.getMessage(), e);
2662         }
2663     }
2664     private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2665         Preconditions.checkNotNull(mdsalConsumer);
2666         if (mdsalConsumer == null) {
2667             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2668             return null;
2669         }
2670
2671         dataBroker = mdsalConsumer.getDataBroker();
2672         if (dataBroker == null) {
2673             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2674             return null;
2675         }
2676
2677         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2678                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
2679                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
2680
2681         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
2682         try {
2683             Optional<Flow> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
2684             if (data.isPresent()) {
2685                 return data.get();
2686             }
2687         } catch (InterruptedException|ExecutionException e) {
2688             logger.error(e.getMessage(), e);
2689         }
2690
2691         logger.debug("Cannot find data for Flow " + flowBuilder.getFlowName());
2692         return null;
2693     }
2694
2695     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2696         Preconditions.checkNotNull(mdsalConsumer);
2697         if (mdsalConsumer == null) {
2698             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
2699             return;
2700         }
2701
2702         dataBroker = mdsalConsumer.getDataBroker();
2703         if (dataBroker == null) {
2704             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2705             return;
2706         }
2707
2708         ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
2709
2710         // Sanity check: do not create parent's tree deeper than we should
2711         InstanceIdentifier<?> requiredPath = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2712                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).build();
2713         try {
2714             if (!modification.read(LogicalDatastoreType.CONFIGURATION, requiredPath).get().isPresent()) {
2715                 logger.error("Unable to get configuration resource to store flow "+flowBuilder.getFlowName()
2716                         +" ("+requiredPath.toString()+")");
2717                 return;
2718             }
2719         } catch (InterruptedException|ExecutionException e) {
2720             logger.error(e.getMessage(), e);
2721             return;
2722         }
2723
2724         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2725                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
2726                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
2727
2728         //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
2729         modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(), true /*createMissingParents*/);
2730
2731
2732         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2733         try {
2734             commitFuture.get();  // TODO: Make it async (See bug 1362)
2735             logger.debug("Transaction success for write of Flow "+flowBuilder.getFlowName());
2736         } catch (InterruptedException|ExecutionException e) {
2737             logger.error(e.getMessage(), e);
2738         }
2739     }
2740
2741     private void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
2742         Preconditions.checkNotNull(mdsalConsumer);
2743         if (mdsalConsumer == null) {
2744             logger.error("ERROR finding MDSAL Service.");
2745             return;
2746         }
2747
2748         dataBroker = mdsalConsumer.getDataBroker();
2749         if (dataBroker == null) {
2750             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
2751             return;
2752         }
2753
2754         WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
2755         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
2756                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
2757                 .rev130819.nodes.Node.class, nodeBuilder.getKey())
2758                 .augmentation(FlowCapableNode.class).child(Table.class,
2759                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
2760         //modification.delete(LogicalDatastoreType.OPERATIONAL, nodeBuilderToInstanceId(nodeBuilder));
2761         //modification.delete(LogicalDatastoreType.OPERATIONAL, path1);
2762         //modification.delete(LogicalDatastoreType.CONFIGURATION, nodeBuilderToInstanceId(nodeBuilder));
2763         modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
2764
2765         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
2766         try {
2767             commitFuture.get();  // TODO: Make it async (See bug 1362)
2768             logger.debug("Transaction success for deletion of Flow "+flowBuilder.getFlowName());
2769         } catch (InterruptedException|ExecutionException e) {
2770             logger.error(e.getMessage(), e);
2771         }
2772     }
2773
2774     /**
2775      * Create Ingress Port Match dpidLong, inPort
2776      *
2777      * @param matchBuilder  Map matchBuilder MatchBuilder Object without a match
2778      * @param dpidLong      Long the datapath ID of a switch/node
2779      * @param inPort        Long ingress port on a switch
2780      * @return matchBuilder Map MatchBuilder Object with a match
2781      */
2782     protected static MatchBuilder createInPortMatch(MatchBuilder matchBuilder, Long dpidLong, Long inPort) {
2783
2784         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + inPort);
2785         logger.debug("createInPortMatch() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, inPort);
2786         matchBuilder.setInPort(NodeConnectorId.getDefaultInstance(ncid.getValue()));
2787         matchBuilder.setInPort(ncid);
2788
2789         return matchBuilder;
2790     }
2791
2792     /**
2793      * Create EtherType Match
2794      *
2795      * @param matchBuilder  Map matchBuilder MatchBuilder Object without a match
2796      * @param etherType     Long EtherType
2797      * @return matchBuilder Map MatchBuilder Object with a match
2798      */
2799     protected static MatchBuilder createEtherTypeMatch(MatchBuilder matchBuilder, EtherType etherType) {
2800
2801         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
2802         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
2803         ethTypeBuilder.setType(new EtherType(etherType));
2804         ethernetMatch.setEthernetType(ethTypeBuilder.build());
2805         matchBuilder.setEthernetMatch(ethernetMatch.build());
2806
2807         return matchBuilder;
2808     }
2809
2810     /**
2811      * Create Ethernet Source Match
2812      *
2813      * @param matchBuilder  MatchBuilder Object without a match yet
2814      * @param sMacAddr      String representing a source MAC
2815      * @return matchBuilder Map MatchBuilder Object with a match
2816      */
2817     protected static MatchBuilder createEthSrcMatch(MatchBuilder matchBuilder, MacAddress sMacAddr) {
2818
2819         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
2820         EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder();
2821         ethSourceBuilder.setAddress(new MacAddress(sMacAddr));
2822         ethernetMatch.setEthernetSource(ethSourceBuilder.build());
2823         matchBuilder.setEthernetMatch(ethernetMatch.build());
2824
2825         return matchBuilder;
2826     }
2827
2828     /**
2829      * Create Ethernet Destination Match
2830      *
2831      * @param matchBuilder MatchBuilder Object without a match yet
2832      * @param vlanId       Integer representing a VLAN ID Integer representing a VLAN ID
2833      * @return matchBuilder Map MatchBuilder Object with a match
2834      */
2835
2836     protected static MatchBuilder createVlanIdMatch(MatchBuilder matchBuilder, VlanId vlanId) {
2837         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
2838         VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
2839         vlanIdBuilder.setVlanId(new VlanId(vlanId));
2840         vlanIdBuilder.setVlanIdPresent(true);
2841         vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
2842         matchBuilder.setVlanMatch(vlanMatchBuilder.build());
2843
2844         return matchBuilder;
2845     }
2846
2847     /**
2848      * Create Ethernet Destination Match
2849      *
2850      * @param matchBuilder  MatchBuilder Object without a match yet
2851      * @param dMacAddr      String representing a destination MAC
2852      * @return matchBuilder Map MatchBuilder Object with a match
2853      */
2854
2855     protected static MatchBuilder createDestEthMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, MacAddress mask) {
2856
2857         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
2858         EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
2859         ethDestinationBuilder.setAddress(new MacAddress(dMacAddr));
2860         if (mask != null) {
2861             ethDestinationBuilder.setMask(mask);
2862         }
2863         ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
2864         matchBuilder.setEthernetMatch(ethernetMatch.build());
2865
2866         return matchBuilder;
2867     }
2868
2869     /**
2870      * Tunnel ID Match Builder
2871      *
2872      * @param matchBuilder  MatchBuilder Object without a match yet
2873      * @param tunnelId      BigInteger representing a tunnel ID
2874      * @return matchBuilder Map MatchBuilder Object with a match
2875      */
2876     protected static MatchBuilder createTunnelIDMatch(MatchBuilder matchBuilder, BigInteger tunnelId) {
2877
2878         TunnelBuilder tunnelBuilder = new TunnelBuilder();
2879         tunnelBuilder.setTunnelId(tunnelId);
2880         matchBuilder.setTunnel(tunnelBuilder.build());
2881
2882         return matchBuilder;
2883     }
2884
2885     /**
2886      * Match ICMP code and type
2887      *
2888      * @param matchBuilder  MatchBuilder Object without a match yet
2889      * @param type          short representing an ICMP type
2890      * @param code          short representing an ICMP code
2891      * @return matchBuilder Map MatchBuilder Object with a match
2892      */
2893     protected static MatchBuilder createICMPv4Match(MatchBuilder matchBuilder, short type, short code) {
2894
2895         EthernetMatchBuilder eth = new EthernetMatchBuilder();
2896         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
2897         ethTypeBuilder.setType(new EtherType(0x0800L));
2898         eth.setEthernetType(ethTypeBuilder.build());
2899         matchBuilder.setEthernetMatch(eth.build());
2900
2901         // Build the IPv4 Match requied per OVS Syntax
2902         IpMatchBuilder ipmatch = new IpMatchBuilder();
2903         ipmatch.setIpProtocol((short) 1);
2904         matchBuilder.setIpMatch(ipmatch.build());
2905
2906         // Build the ICMPv4 Match
2907         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
2908         icmpv4match.setIcmpv4Type(type);
2909         icmpv4match.setIcmpv4Code(code);
2910         matchBuilder.setIcmpv4Match(icmpv4match.build());
2911
2912         return matchBuilder;
2913     }
2914
2915     /**
2916      * @param matchBuilder MatchBuilder Object without a match yet
2917      * @param dstip        String containing an IPv4 prefix
2918      * @return matchBuilder Map Object with a match
2919      */
2920     private static MatchBuilder createDstL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix dstip) {
2921
2922         EthernetMatchBuilder eth = new EthernetMatchBuilder();
2923         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
2924         ethTypeBuilder.setType(new EtherType(0x0800L));
2925         eth.setEthernetType(ethTypeBuilder.build());
2926         matchBuilder.setEthernetMatch(eth.build());
2927
2928         Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
2929         ipv4match.setIpv4Destination(dstip);
2930
2931         matchBuilder.setLayer3Match(ipv4match.build());
2932
2933         return matchBuilder;
2934
2935     }
2936
2937     /**
2938      * @param matchBuilder MatchBuilder Object without a match yet
2939      * @param srcip        String containing an IPv4 prefix
2940      * @return             matchBuilder Map Object with a match
2941      */
2942     private static MatchBuilder createSrcL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix srcip) {
2943
2944         EthernetMatchBuilder eth = new EthernetMatchBuilder();
2945         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
2946         ethTypeBuilder.setType(new EtherType(0x0800L));
2947         eth.setEthernetType(ethTypeBuilder.build());
2948         matchBuilder.setEthernetMatch(eth.build());
2949
2950         Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder();
2951         Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
2952         ipv4match.setIpv4Source(srcip);
2953         matchBuilder.setLayer3Match(ipv4match.build());
2954
2955         return matchBuilder;
2956
2957     }
2958
2959     /**
2960      * Create Source TCP Port Match
2961      *
2962      * @param matchBuilder @param matchbuilder MatchBuilder Object without a match yet
2963      * @param tcpport      Integer representing a source TCP port
2964      * @return             matchBuilder Map MatchBuilder Object with a match
2965      */
2966     protected static MatchBuilder createSetSrcTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) {
2967
2968         EthernetMatchBuilder ethType = new EthernetMatchBuilder();
2969         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
2970         ethTypeBuilder.setType(new EtherType(0x0800L));
2971         ethType.setEthernetType(ethTypeBuilder.build());
2972         matchBuilder.setEthernetMatch(ethType.build());
2973
2974         IpMatchBuilder ipmatch = new IpMatchBuilder();
2975         ipmatch.setIpProtocol((short) 6);
2976         matchBuilder.setIpMatch(ipmatch.build());
2977
2978         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
2979         tcpmatch.setTcpSourcePort(tcpport);
2980         matchBuilder.setLayer4Match(tcpmatch.build());
2981
2982         return matchBuilder;
2983
2984     }
2985
2986     /**
2987      * Create Destination TCP Port Match
2988      *
2989      * @param matchBuilder MatchBuilder Object without a match yet
2990      * @param tcpport      Integer representing a destination TCP port
2991      * @return             matchBuilder Map MatchBuilder Object with a match
2992      */
2993     protected static MatchBuilder createSetDstTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) {
2994
2995         EthernetMatchBuilder ethType = new EthernetMatchBuilder();
2996         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
2997         ethTypeBuilder.setType(new EtherType(0x0800L));
2998         ethType.setEthernetType(ethTypeBuilder.build());
2999         matchBuilder.setEthernetMatch(ethType.build());
3000
3001         IpMatchBuilder ipmatch = new IpMatchBuilder();
3002         ipmatch.setIpProtocol((short) 6);
3003         matchBuilder.setIpMatch(ipmatch.build());
3004
3005         PortNumber dstport = new PortNumber(tcpport);
3006         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
3007
3008         tcpmatch.setTcpDestinationPort(tcpport);
3009         matchBuilder.setLayer4Match(tcpmatch.build());
3010
3011         return matchBuilder;
3012     }
3013
3014     /**
3015      * Create Send to Controller Reserved Port Instruction (packet_in)
3016      *
3017      * @param ib Map InstructionBuilder without any instructions
3018      * @return ib Map InstructionBuilder with instructions
3019      */
3020
3021     protected static InstructionBuilder createSendToControllerInstructions(InstructionBuilder ib) {
3022
3023         List<Action> actionList = Lists.newArrayList();
3024         ActionBuilder ab = new ActionBuilder();
3025
3026         OutputActionBuilder output = new OutputActionBuilder();
3027         output.setMaxLength(0xffff);
3028         Uri value = new Uri("CONTROLLER");
3029         output.setOutputNodeConnector(value);
3030         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
3031         ab.setOrder(0);
3032         ab.setKey(new ActionKey(0));
3033         actionList.add(ab.build());
3034
3035         // Create an Apply Action
3036         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3037         aab.setAction(actionList);
3038
3039         // Wrap our Apply Action in an Instruction
3040         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3041
3042         return ib;
3043     }
3044
3045     /**
3046      * Create NORMAL Reserved Port Instruction (packet_in)
3047      *
3048      * @param ib Map InstructionBuilder without any instructions
3049      * @return ib Map InstructionBuilder with instructions
3050      */
3051
3052     protected static InstructionBuilder createNormalInstructions(InstructionBuilder ib) {
3053
3054         List<Action> actionList = Lists.newArrayList();
3055         ActionBuilder ab = new ActionBuilder();
3056
3057         OutputActionBuilder output = new OutputActionBuilder();
3058         Uri value = new Uri("NORMAL");
3059         output.setOutputNodeConnector(value);
3060         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
3061         ab.setOrder(0);
3062         ab.setKey(new ActionKey(0));
3063         actionList.add(ab.build());
3064
3065         // Create an Apply Action
3066         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3067         aab.setAction(actionList);
3068
3069         // Wrap our Apply Action in an Instruction
3070         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3071
3072         return ib;
3073     }
3074
3075     /**
3076      * Create Output Port Instruction
3077      *
3078      * @param ib       Map InstructionBuilder without any instructions
3079      * @param dpidLong Long the datapath ID of a switch/node
3080      * @param port     Long representing a port on a switch/node
3081      * @return ib InstructionBuilder Map with instructions
3082      */
3083     protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port) {
3084
3085         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
3086         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, port);
3087
3088         List<Action> actionList = Lists.newArrayList();
3089         ActionBuilder ab = new ActionBuilder();
3090         OutputActionBuilder oab = new OutputActionBuilder();
3091         oab.setOutputNodeConnector(ncid);
3092
3093         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
3094         ab.setOrder(0);
3095         ab.setKey(new ActionKey(0));
3096         actionList.add(ab.build());
3097
3098         // Create an Apply Action
3099         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3100         aab.setAction(actionList);
3101         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3102
3103         return ib;
3104     }
3105
3106     /**
3107      * Create Output Port Group Instruction
3108      *
3109      * @param ib       Map InstructionBuilder without any instructions
3110      * @param dpidLong Long the datapath ID of a switch/node
3111      * @param port     Long representing a port on a switch/node
3112      * @return ib InstructionBuilder Map with instructions
3113      */
3114     protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
3115                                                               Long dpidLong, Long port ,
3116                                                               List<Instruction> instructions) {
3117         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
3118         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
3119
3120         List<Action> actionList = Lists.newArrayList();
3121         ActionBuilder ab = new ActionBuilder();
3122
3123         List<Action> existingActions;
3124         if (instructions != null) {
3125             for (Instruction in : instructions) {
3126                 if (in.getInstruction() instanceof ApplyActionsCase) {
3127                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
3128                     actionList.addAll(existingActions);
3129                 }
3130             }
3131         }
3132         /* Create output action for this port*/
3133         OutputActionBuilder oab = new OutputActionBuilder();
3134         oab.setOutputNodeConnector(ncid);
3135         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
3136         boolean addNew = true;
3137
3138         /* Find the group action and get the group */
3139         for (Action action : actionList) {
3140             if (action.getAction() instanceof OutputActionCase) {
3141                 OutputActionCase opAction = (OutputActionCase)action.getAction();
3142                 /* If output port action already in the action list of one of the buckets, skip */
3143                 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
3144                     addNew = false;
3145                     break;
3146                 }
3147             }
3148         }
3149         if (addNew) {
3150             ab.setOrder(actionList.size());
3151             ab.setKey(new ActionKey(actionList.size()));
3152             actionList.add(ab.build());
3153         }
3154         // Create an Apply Action
3155         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3156         aab.setAction(actionList);
3157         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3158         logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());
3159         return ib;
3160     }
3161
3162     /**
3163      * Create Output Port Group Instruction
3164      *
3165      * @param ib       Map InstructionBuilder without any instructions
3166      * @param dpidLong Long the datapath ID of a switch/node
3167      * @param port     Long representing a port on a switch/node
3168      * @return ib InstructionBuilder Map with instructions
3169      */
3170     protected InstructionBuilder createOutputGroupInstructions(NodeBuilder nodeBuilder,
3171                                                                InstructionBuilder ib,
3172                                                                Long dpidLong, Long port ,
3173                                                                List<Instruction> instructions) {
3174         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
3175         logger.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
3176
3177         List<Action> actionList = Lists.newArrayList();
3178         ActionBuilder ab = new ActionBuilder();
3179
3180         List<Action> existingActions;
3181         if (instructions != null) {
3182             for (Instruction in : instructions) {
3183                 if (in.getInstruction() instanceof ApplyActionsCase) {
3184                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
3185                     actionList.addAll(existingActions);
3186                 }
3187             }
3188         }
3189
3190         GroupBuilder groupBuilder = new GroupBuilder();
3191         Group group = null;
3192
3193         /* Create output action for this port*/
3194         OutputActionBuilder oab = new OutputActionBuilder();
3195         oab.setOutputNodeConnector(ncid);
3196         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
3197         logger.debug("createOutputGroupInstructions(): output action {}", ab.build());
3198         boolean addNew = true;
3199         boolean groupActionAdded = false;
3200
3201         /* Find the group action and get the group */
3202         for (Action action : actionList) {
3203             if (action.getAction() instanceof GroupActionCase) {
3204                 groupActionAdded = true;
3205                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
3206                 Long id = groupAction.getGroupAction().getGroupId();
3207                 String groupName = groupAction.getGroupAction().getGroup();
3208                 GroupKey key = new GroupKey(new GroupId(id));
3209
3210                 groupBuilder.setGroupId(new GroupId(id));
3211                 groupBuilder.setGroupName(groupName);
3212                 groupBuilder.setGroupType(GroupTypes.GroupAll);
3213                 groupBuilder.setKey(key);
3214                 group = getGroup(groupBuilder, nodeBuilder);
3215                 logger.debug("createOutputGroupInstructions: group {}", group);
3216                 break;
3217             }
3218         }
3219
3220         logger.debug("createOutputGroupInstructions: groupActionAdded {}", groupActionAdded);
3221         if (groupActionAdded) {
3222             /* modify the action bucket in group */
3223             groupBuilder = new GroupBuilder(group);
3224             Buckets buckets = groupBuilder.getBuckets();
3225             for (Bucket bucket : buckets.getBucket()) {
3226                 List<Action> bucketActions = bucket.getAction();
3227                 logger.debug("createOutputGroupInstructions: bucketActions {}", bucketActions);
3228                 for (Action action : bucketActions) {
3229                     if (action.getAction() instanceof OutputActionCase) {
3230                         OutputActionCase opAction = (OutputActionCase)action.getAction();
3231                         /* If output port action already in the action list of one of the buckets, skip */
3232                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
3233                             addNew = false;
3234                             break;
3235                         }
3236                     }
3237                 }
3238             }
3239             logger.debug("createOutputGroupInstructions: addNew {}", addNew);
3240             if (addNew) {
3241                 /* the new output action is not in the bucket, add to bucket */
3242                 if (!buckets.getBucket().isEmpty()) {
3243                     Bucket bucket = buckets.getBucket().get(0);
3244                     List<Action> bucketActionList = Lists.newArrayList();
3245                     bucketActionList.addAll(bucket.getAction());
3246                     /* set order for new action and add to action list */
3247                     ab.setOrder(bucketActionList.size());
3248                     ab.setKey(new ActionKey(bucketActionList.size()));
3249                     bucketActionList.add(ab.build());
3250
3251                     /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
3252                     BucketsBuilder bucketsBuilder = new BucketsBuilder();
3253                     List<Bucket> bucketList = Lists.newArrayList();
3254                     BucketBuilder bucketBuilder = new BucketBuilder();
3255                     bucketBuilder.setBucketId(new BucketId((long) 1));
3256                     bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
3257                     bucketBuilder.setAction(bucketActionList);
3258                     bucketList.add(bucketBuilder.build());
3259                     bucketsBuilder.setBucket(bucketList);
3260                     groupBuilder.setBuckets(bucketsBuilder.build());
3261                     logger.debug("createOutputGroupInstructions: bucketList {}", bucketList);
3262                 }
3263             }
3264         } else {
3265             /* create group */
3266             groupBuilder = new GroupBuilder();
3267             groupBuilder.setGroupType(GroupTypes.GroupAll);
3268             groupBuilder.setGroupId(new GroupId(groupId));
3269             groupBuilder.setKey(new GroupKey(new GroupId(groupId)));
3270             groupBuilder.setGroupName("Output port group" + groupId);
3271             groupBuilder.setBarrier(false);
3272
3273             BucketsBuilder bucketBuilder = new BucketsBuilder();
3274             List<Bucket> bucketList = Lists.newArrayList();
3275             BucketBuilder bucket = new BucketBuilder();
3276             bucket.setBucketId(new BucketId((long) 1));
3277             bucket.setKey(new BucketKey(new BucketId((long) 1)));
3278
3279             /* put output action to the bucket */
3280             List<Action> bucketActionList = Lists.newArrayList();
3281             /* set order for new action and add to action list */
3282             ab.setOrder(bucketActionList.size());
3283             ab.setKey(new ActionKey(bucketActionList.size()));
3284             bucketActionList.add(ab.build());
3285
3286             bucket.setAction(bucketActionList);
3287             bucketList.add(bucket.build());
3288             bucketBuilder.setBucket(bucketList);
3289             groupBuilder.setBuckets(bucketBuilder.build());
3290
3291             /* Add new group action */
3292             GroupActionBuilder groupActionB = new GroupActionBuilder();
3293             groupActionB.setGroupId(groupId);
3294             groupActionB.setGroup("Output port group" + groupId);
3295             ab = new ActionBuilder();
3296             ab.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionB.build()).build());
3297             ab.setOrder(actionList.size());
3298             ab.setKey(new ActionKey(actionList.size()));
3299             actionList.add(ab.build());
3300
3301             groupId++;
3302         }
3303         logger.debug("createOutputGroupInstructions: group {}", groupBuilder.build());
3304         logger.debug("createOutputGroupInstructions: actionList {}", actionList);
3305
3306         if (addNew) {
3307             /* rewrite the group to group table */
3308             writeGroup(groupBuilder, nodeBuilder);
3309         }
3310
3311         // Create an Apply Action
3312         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3313         aab.setAction(actionList);
3314         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3315
3316         return ib;
3317     }
3318
3319     /**
3320      * add Output Port action to Instruction action list.
3321      * This is use for flow with single output port actions.
3322      * Flow with mutiple output port actions should use createOutputPortInstructions() method.
3323      *
3324      * @param ib       Map InstructionBuilder without any instructions
3325      * @param dpidLong Long the datapath ID of a switch/node
3326      * @param port     Long representing a port on a switch/node
3327      * @return ib InstructionBuilder Map with instructions
3328      */
3329     protected static InstructionBuilder addOutputPortInstructions(InstructionBuilder ib,
3330                                                                      Long dpidLong, Long port ,
3331                                                                      List<Instruction> instructions) {
3332         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
3333         logger.debug("addOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
3334
3335         List<Action> actionList = Lists.newArrayList();
3336         ActionBuilder ab = new ActionBuilder();
3337
3338         List<Action> existingActions;
3339         if (instructions != null) {
3340             for (Instruction in : instructions) {
3341                 if (in.getInstruction() instanceof ApplyActionsCase) {
3342                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
3343                     actionList.addAll(existingActions);
3344                 }
3345             }
3346         }
3347
3348         /* Create output action for this port*/
3349         OutputActionBuilder oab = new OutputActionBuilder();
3350         oab.setOutputNodeConnector(ncid);
3351         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
3352         ab.setOrder(actionList.size());
3353         ab.setKey(new ActionKey(actionList.size()));
3354         actionList.add(ab.build());
3355
3356         // Create an Apply Action
3357         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3358         aab.setAction(actionList);
3359         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3360
3361         return ib;
3362     }
3363
3364     /**
3365      * Remove Output Port from action list in group bucket
3366      *
3367      * @param ib       Map InstructionBuilder without any instructions
3368      * @param dpidLong Long the datapath ID of a switch/node
3369      * @param port     Long representing a port on a switch/node
3370      * @return ib InstructionBuilder Map with instructions
3371      */
3372     protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
3373                                 Long dpidLong, Long port , List<Instruction> instructions) {
3374
3375         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
3376         logger.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
3377
3378         List<Action> actionList = Lists.newArrayList();
3379         ActionBuilder ab;
3380
3381         List<Action> existingActions;
3382         if (instructions != null) {
3383             for (Instruction in : instructions) {
3384                 if (in.getInstruction() instanceof ApplyActionsCase) {
3385                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
3386                     actionList.addAll(existingActions);
3387                     break;
3388                 }
3389             }
3390         }
3391
3392         GroupBuilder groupBuilder = new GroupBuilder();
3393         Group group = null;
3394         boolean groupActionAdded = false;
3395         /* Find the group action and get the group */
3396         for (Action action : actionList) {
3397             if (action.getAction() instanceof GroupActionCase) {
3398                 groupActionAdded = true;
3399                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
3400                 Long id = groupAction.getGroupAction().getGroupId();
3401                 String groupName = groupAction.getGroupAction().getGroup();
3402                 GroupKey key = new GroupKey(new GroupId(id));
3403
3404                 groupBuilder.setGroupId(new GroupId(id));
3405                 groupBuilder.setGroupName(groupName);
3406                 groupBuilder.setGroupType(GroupTypes.GroupAll);
3407                 groupBuilder.setKey(key);
3408                 group = getGroup(groupBuilder, nodeBuilder);
3409                 break;
3410             }
3411         }
3412
3413         if (groupActionAdded) {
3414             /* modify the action bucket in group */
3415             groupBuilder = new GroupBuilder(group);
3416             Buckets buckets = groupBuilder.getBuckets();
3417             List<Action> bucketActions = Lists.newArrayList();
3418             for (Bucket bucket : buckets.getBucket()) {
3419                 int index = 0;
3420                 boolean isPortDeleted = false;
3421                 bucketActions = bucket.getAction();
3422                 for (Action action : bucketActions) {
3423                     if (action.getAction() instanceof OutputActionCase) {
3424                         OutputActionCase opAction = (OutputActionCase)action.getAction();
3425                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
3426                             /* Find the output port in action list and remove */
3427                             index = bucketActions.indexOf(action);
3428                             bucketActions.remove(action);
3429                             isPortDeleted = true;
3430                             break;
3431                         }
3432                     }
3433                 }
3434                 if (isPortDeleted && !bucketActions.isEmpty()) {
3435                     for (int i = index; i< bucketActions.size(); i++) {
3436                         Action action = bucketActions.get(i);
3437                         if (action.getOrder() != i) {
3438                             /* Shift the action order */
3439                             ab = new ActionBuilder();
3440                             ab.setAction(action.getAction());
3441                             ab.setOrder(i);
3442                             ab.setKey(new ActionKey(i));
3443                             Action actionNewOrder = ab.build();
3444                             bucketActions.remove(action);
3445                             bucketActions.add(i, actionNewOrder);
3446                         }
3447                     }
3448
3449                 } else if (bucketActions.isEmpty()) {
3450                     /* remove bucket with empty action list */
3451                     buckets.getBucket().remove(bucket);
3452                     break;
3453                 }
3454             }
3455             if (!buckets.getBucket().isEmpty()) {
3456                 /* rewrite the group to group table */
3457                 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
3458                 BucketsBuilder bucketsBuilder = new BucketsBuilder();
3459                 List<Bucket> bucketList = Lists.newArrayList();
3460                 BucketBuilder bucketBuilder = new BucketBuilder();
3461                 bucketBuilder.setBucketId(new BucketId((long) 1));
3462                 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
3463                 bucketBuilder.setAction(bucketActions);
3464                 bucketList.add(bucketBuilder.build());
3465                 bucketsBuilder.setBucket(bucketList);
3466                 groupBuilder.setBuckets(bucketsBuilder.build());
3467                 logger.debug("removeOutputPortFromGroup: bucketList {}", bucketList);
3468
3469                 writeGroup(groupBuilder, nodeBuilder);
3470                 ApplyActionsBuilder aab = new ApplyActionsBuilder();
3471                 aab.setAction(actionList);
3472                 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3473                 return false;
3474             } else {
3475                 /* remove group with empty bucket. return true to delete flow */
3476                 removeGroup(groupBuilder, nodeBuilder);
3477                 return true;
3478             }
3479         } else {
3480             /* no group for port list. flow can be removed */
3481             return true;
3482         }
3483     }
3484
3485     /**
3486      * Remove Output Port from Instruction
3487      *
3488      * @param ib       Map InstructionBuilder without any instructions
3489      * @param dpidLong Long the datapath ID of a switch/node
3490      * @param port     Long representing a port on a switch/node
3491      * @return ib InstructionBuilder Map with instructions
3492      */
3493     protected static boolean removeOutputPortFromInstructions(InstructionBuilder ib,
3494                                 Long dpidLong, Long port , List<Instruction> instructions) {
3495
3496         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
3497         logger.debug("removeOutputPortFromInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
3498
3499         List<Action> actionList = Lists.newArrayList();
3500         ActionBuilder ab;
3501
3502         List<Action> existingActions;
3503         if (instructions != null) {
3504             for (Instruction in : instructions) {
3505                 if (in.getInstruction() instanceof ApplyActionsCase) {
3506                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
3507                     actionList.addAll(existingActions);
3508                     break;
3509                 }
3510             }
3511         }
3512
3513         int index = 0;
3514         boolean isPortDeleted = false;
3515         boolean removeFlow = true;
3516         for (Action action : actionList) {
3517             if (action.getAction() instanceof OutputActionCase) {
3518                 OutputActionCase opAction = (OutputActionCase)action.getAction();
3519                 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
3520                     /* Find the output port in action list and remove */
3521                     index = actionList.indexOf(action);
3522                     actionList.remove(action);
3523                     isPortDeleted = true;
3524                     break;
3525                 }
3526                 removeFlow = false;
3527             }
3528         }
3529
3530         if (isPortDeleted) {
3531             for (int i = index; i< actionList.size(); i++) {
3532                 Action action = actionList.get(i);
3533                 if (action.getOrder() != i) {
3534                     /* Shift the action order */
3535                     ab = new ActionBuilder();
3536                     ab.setAction(action.getAction());
3537                     ab.setOrder(i);
3538                     ab.setKey(new ActionKey(i));
3539                     Action actionNewOrder = ab.build();
3540                     actionList.remove(action);
3541                     actionList.add(i, actionNewOrder);
3542                 }
3543                 if (action.getAction() instanceof OutputActionCase) {
3544                     removeFlow = false;
3545                 }
3546             }
3547         }
3548
3549         /* Put new action list in Apply Action instruction */
3550         if (!removeFlow) {
3551             ApplyActionsBuilder aab = new ApplyActionsBuilder();
3552             aab.setAction(actionList);
3553             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3554             logger.debug("removeOutputPortFromInstructions() : applyAction {}", aab.build());
3555             return false;
3556         } else {
3557             /* if all output port are removed. Return true to indicate flow remove */
3558             return true;
3559         }
3560     }
3561
3562     /**
3563      * Create Set Vlan ID Instruction - This includes push vlan action, and set field -> vlan vid action
3564      *
3565      * @param ib     Map InstructionBuilder without any instructions
3566      * @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID
3567      * @return ib Map InstructionBuilder with instructions
3568      */
3569     protected static InstructionBuilder createSetVlanInstructions(InstructionBuilder ib, VlanId vlanId) {
3570
3571         List<Action> actionList = Lists.newArrayList();
3572         ActionBuilder ab = new ActionBuilder();
3573
3574         /* First we push vlan header */
3575         PushVlanActionBuilder vlan = new PushVlanActionBuilder();
3576         vlan.setEthernetType(new Integer(0x8100));
3577         ab.setAction(new PushVlanActionCaseBuilder().setPushVlanAction(vlan.build()).build());
3578         ab.setOrder(0);
3579         actionList.add(ab.build());
3580
3581         /* Then we set vlan id value as vlanId */
3582         SetVlanIdActionBuilder vl = new SetVlanIdActionBuilder();
3583         vl.setVlanId(vlanId);
3584         ab = new ActionBuilder();
3585         ab.setAction(new SetVlanIdActionCaseBuilder().setSetVlanIdAction(vl.build()).build());
3586         ab.setOrder(1);
3587         actionList.add(ab.build());
3588         // Create an Apply Action
3589         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3590         aab.setAction(actionList);
3591
3592         // Wrap our Apply Action in an Instruction
3593         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3594
3595         return ib;
3596     }
3597
3598     /**
3599      * Create Pop Vlan Instruction - this remove vlan header
3600      *
3601      * @param ib Map InstructionBuilder without any instructions
3602      * @return ib Map InstructionBuilder with instructions
3603      */
3604     protected static InstructionBuilder createPopVlanInstructions(InstructionBuilder ib) {
3605
3606         List<Action> actionList = Lists.newArrayList();
3607         ActionBuilder ab = new ActionBuilder();
3608
3609         PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
3610         ab.setAction(new PopVlanActionCaseBuilder().setPopVlanAction(popVlanActionBuilder.build()).build());
3611         ab.setOrder(0);
3612         actionList.add(ab.build());
3613
3614         // Create an Apply Action
3615         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3616         aab.setAction(actionList);
3617
3618         // Wrap our Apply Action in an Instruction
3619         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3620
3621         return ib;
3622     }
3623
3624     /**
3625      * Create Set IPv4 Source Instruction
3626      *
3627      * @param ib        Map InstructionBuilder without any instructions
3628      * @param prefixsrc String containing an IPv4 prefix
3629      * @return ib Map InstructionBuilder with instructions
3630      */
3631     protected static InstructionBuilder createNwSrcInstructions(InstructionBuilder ib, Ipv4Prefix prefixsrc) {
3632
3633         List<Action> actionList = Lists.newArrayList();
3634         ActionBuilder ab = new ActionBuilder();
3635
3636         SetNwSrcActionBuilder setNwsrcActionBuilder = new SetNwSrcActionBuilder();
3637         Ipv4Builder ipsrc = new Ipv4Builder();
3638         ipsrc.setIpv4Address(prefixsrc);
3639         setNwsrcActionBuilder.setAddress(ipsrc.build());
3640         ab.setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwsrcActionBuilder.build()).build());
3641         actionList.add(ab.build());
3642
3643         // Create an Apply Action
3644         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3645         aab.setAction(actionList);
3646
3647         // Wrap our Apply Action in an Instruction
3648         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3649
3650         return ib;
3651     }
3652
3653     /**
3654      * Create Set IPv4 Destination Instruction
3655      *
3656      * @param ib           Map InstructionBuilder without any instructions
3657      * @param prefixdst    String containing an IPv4 prefix
3658      * @return ib Map InstructionBuilder with instructions
3659      */
3660     protected static InstructionBuilder createNwDstInstructions(InstructionBuilder ib, Ipv4Prefix prefixdst) {
3661
3662         List<Action> actionList = Lists.newArrayList();
3663         ActionBuilder ab = new ActionBuilder();
3664
3665         SetNwDstActionBuilder setNwDstActionBuilder = new SetNwDstActionBuilder();
3666         Ipv4Builder ipdst = new Ipv4Builder();
3667         ipdst.setIpv4Address(prefixdst);
3668         setNwDstActionBuilder.setAddress(ipdst.build());
3669         ab.setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilder.build()).build());
3670         actionList.add(ab.build());
3671
3672         // Create an Apply Action
3673         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3674         aab.setAction(actionList);
3675
3676         // Wrap our Apply Action in an Instruction
3677         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3678
3679         return ib;
3680     }
3681
3682     /**
3683      * Create Drop Instruction
3684      *
3685      * @param ib Map InstructionBuilder without any instructions
3686      * @return ib Map InstructionBuilder with instructions
3687      */
3688     protected static InstructionBuilder createDropInstructions(InstructionBuilder ib) {
3689
3690         DropActionBuilder dab = new DropActionBuilder();
3691         DropAction dropAction = dab.build();
3692         ActionBuilder ab = new ActionBuilder();
3693         ab.setAction(new DropActionCaseBuilder().setDropAction(dropAction).build());
3694         ab.setOrder(0);
3695
3696         // Add our drop action to a list
3697         List<Action> actionList = Lists.newArrayList();
3698         actionList.add(ab.build());
3699
3700         // Create an Apply Action
3701         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3702         aab.setAction(actionList);
3703
3704         // Wrap our Apply Action in an Instruction
3705         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3706
3707         return ib;
3708     }
3709
3710     /**
3711      * Create GOTO Table Instruction Builder
3712      *
3713      * @param ib      Map InstructionBuilder without any instructions
3714      * @param tableId short representing a flow table ID short representing a flow table ID
3715      * @return ib Map InstructionBuilder with instructions
3716      */
3717     protected static InstructionBuilder createGotoTableInstructions(InstructionBuilder ib, short tableId) {
3718
3719         GoToTableBuilder gttb = new GoToTableBuilder();
3720         gttb.setTableId(tableId);
3721
3722         // Wrap our Apply Action in an InstructionBuilder
3723         ib.setInstruction(new GoToTableCaseBuilder().setGoToTable(gttb.build()).build());
3724
3725         return ib;
3726     }
3727
3728     /**
3729      * Create Set Tunnel ID Instruction Builder
3730      *
3731      * @param ib       Map InstructionBuilder without any instructions
3732      * @param tunnelId BigInteger representing a tunnel ID
3733      * @return ib Map InstructionBuilder with instructions
3734      */
3735     protected static InstructionBuilder createSetTunnelIdInstructions(InstructionBuilder ib, BigInteger tunnelId) {
3736
3737         List<Action> actionList = Lists.newArrayList();
3738         ActionBuilder ab = new ActionBuilder();
3739         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3740
3741         // Build the Set Tunnel Field Action
3742         TunnelBuilder tunnel = new TunnelBuilder();
3743         tunnel.setTunnelId(tunnelId);
3744         setFieldBuilder.setTunnel(tunnel.build());
3745         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3746         ab.setOrder(0);
3747         actionList.add(ab.build());
3748
3749         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3750         aab.setAction(actionList);
3751
3752         // Wrap the Apply Action in an InstructionBuilder and return
3753         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3754
3755         return ib;
3756     }
3757
3758     /**
3759      * Create Set Source TCP Port Instruction
3760      *
3761      * @param ib      Map InstructionBuilder without any instructions
3762      * @param tcpport Integer representing a source TCP port
3763      * @return ib Map InstructionBuilder with instructions
3764      */
3765     protected static InstructionBuilder createSetSrcTCPPort(InstructionBuilder ib, PortNumber tcpport) {
3766
3767         List<Action> actionList = Lists.newArrayList();
3768         ActionBuilder ab = new ActionBuilder();
3769         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3770
3771         // Build the Destination TCP Port
3772         PortNumber tcpsrcport = new PortNumber(tcpport);
3773         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
3774         tcpmatch.setTcpSourcePort(tcpsrcport);
3775
3776         setFieldBuilder.setLayer4Match(tcpmatch.build());
3777         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3778         ab.setKey(new ActionKey(1));
3779         actionList.add(ab.build());
3780
3781         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3782         aab.setAction(actionList);
3783         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3784
3785         return ib;
3786     }
3787
3788     /**
3789      * Create Set Destination TCP Port Instruction
3790      *
3791      * @param ib      Map InstructionBuilder without any instructions
3792      * @param tcpport Integer representing a source TCP port
3793      * @return ib Map InstructionBuilder with instructions
3794      */
3795     protected static InstructionBuilder createSetDstTCPPort(InstructionBuilder ib, PortNumber tcpport) {
3796
3797         List<Action> actionList = Lists.newArrayList();
3798         ActionBuilder ab = new ActionBuilder();
3799         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3800
3801         // Build the Destination TCP Port
3802         PortNumber tcpdstport = new PortNumber(tcpport);
3803         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
3804         tcpmatch.setTcpDestinationPort(tcpdstport);
3805
3806         setFieldBuilder.setLayer4Match(tcpmatch.build());
3807         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3808         ab.setKey(new ActionKey(1));
3809         actionList.add(ab.build());
3810
3811         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3812         aab.setAction(actionList);
3813         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3814
3815         return ib;
3816     }
3817
3818     /**
3819      * Create Set Source UDP Port Instruction
3820      *
3821      * @param ib      Map InstructionBuilder without any instructions
3822      * @param udpport Integer representing a source UDP port
3823      * @return ib Map InstructionBuilder with instructions
3824      */
3825     protected static InstructionBuilder createSetSrcUDPPort(InstructionBuilder ib, PortNumber udpport) {
3826
3827         List<Action> actionList = Lists.newArrayList();
3828         ActionBuilder ab = new ActionBuilder();
3829         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3830
3831         // Build the Destination TCP Port
3832         PortNumber udpsrcport = new PortNumber(udpport);
3833         UdpMatchBuilder udpmatch = new UdpMatchBuilder();
3834         udpmatch.setUdpSourcePort(udpsrcport);
3835
3836         setFieldBuilder.setLayer4Match(udpmatch.build());
3837         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3838         ab.setKey(new ActionKey(1));
3839         actionList.add(ab.build());
3840
3841         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3842         aab.setAction(actionList);
3843         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3844
3845         return ib;
3846     }
3847
3848     /**
3849      * Create Set Destination UDP Port Instruction
3850      *
3851      * @param ib      Map InstructionBuilder without any instructions
3852      * @param udpport Integer representing a destination UDP port
3853      * @return ib Map InstructionBuilder with instructions
3854      */
3855     protected static InstructionBuilder createSetDstUDPPort(InstructionBuilder ib, PortNumber udpport) {
3856
3857         List<Action> actionList = Lists.newArrayList();
3858         ActionBuilder ab = new ActionBuilder();
3859         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3860
3861         // Build the Destination TCP Port
3862         PortNumber udpdstport = new PortNumber(udpport);
3863         UdpMatchBuilder udpmatch = new UdpMatchBuilder();
3864         udpmatch.setUdpDestinationPort(udpdstport);
3865
3866         setFieldBuilder.setLayer4Match(udpmatch.build());
3867         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3868         ab.setKey(new ActionKey(1));
3869         actionList.add(ab.build());
3870
3871         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3872         aab.setAction(actionList);
3873         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3874
3875         return ib;
3876     }
3877
3878     /**
3879      * Create Set ICMP Code Instruction
3880      *
3881      * @param ib   Map InstructionBuilder without any instructions
3882      * @param code short repesenting an ICMP code
3883      * @return ib Map InstructionBuilder with instructions
3884      */
3885
3886     private static InstructionBuilder createSetIcmpCodeInstruction(InstructionBuilder ib, short code) {
3887
3888         List<Action> actionList = Lists.newArrayList();
3889         ActionBuilder ab = new ActionBuilder();
3890         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3891         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
3892
3893         // Build the ICMPv4 Code Match
3894         icmpv4match.setIcmpv4Code(code);
3895         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
3896
3897         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3898         ab.setKey(new ActionKey(0));
3899         actionList.add(ab.build());
3900         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3901         aab.setAction(actionList);
3902
3903         // Wrap our Apply Action in an Instruction
3904         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3905
3906         return ib;
3907     }
3908
3909     /**
3910      * Create Set ICMP Code Instruction
3911      *
3912      * @param ib Map InstructionBuilder without any instructions
3913      * @return ib Map InstructionBuilder with instructions
3914      */
3915     private static InstructionBuilder createSetIcmpTypeInstruction(InstructionBuilder ib, short type) {
3916
3917         List<Action> actionList = Lists.newArrayList();
3918         ActionBuilder ab = new ActionBuilder();
3919         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3920         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
3921
3922         // Build the ICMPv4 Code Match
3923         icmpv4match.setIcmpv4Code(type);
3924         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
3925
3926         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3927         ab.setKey(new ActionKey(1));
3928         actionList.add(ab.build());
3929         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3930         aab.setAction(actionList);
3931
3932         // Wrap our Apply Action in an Instruction
3933         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3934
3935         return ib;
3936     }
3937
3938     /**
3939      * Create Decrement TTL Instruction
3940      *
3941      * @param ib Map InstructionBuilder without any instructions
3942      * @return ib Map InstructionBuilder with instructions
3943      */
3944     private static InstructionBuilder createDecNwTtlInstructions(InstructionBuilder ib) {
3945         DecNwTtlBuilder decNwTtlBuilder = new DecNwTtlBuilder();
3946         DecNwTtl decNwTtl = decNwTtlBuilder.build();
3947         ActionBuilder ab = new ActionBuilder();
3948         ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build());
3949
3950         // Add our drop action to a list
3951         List<Action> actionList = Lists.newArrayList();
3952         actionList.add(ab.build());
3953
3954         // Create an Apply Action
3955         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3956         aab.setAction(actionList);
3957
3958         // Wrap our Apply Action in an Instruction
3959         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
3960
3961         return ib;
3962     }
3963
3964     /**
3965      * Set Src Arp MAC
3966      */
3967     private static InstructionBuilder createSrcArpMacInstructions(InstructionBuilder ib, MacAddress macsrc) {
3968
3969         List<Action> actionList = Lists.newArrayList();
3970         ActionBuilder ab = new ActionBuilder();
3971
3972         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3973         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
3974         ArpSourceHardwareAddressBuilder arpsrc = new ArpSourceHardwareAddressBuilder();
3975         arpsrc.setAddress(macsrc);
3976         arpmatch.setArpSourceHardwareAddress(arpsrc.build());
3977         setFieldBuilder.setLayer3Match(arpmatch.build());
3978         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
3979         ab.setKey(new ActionKey(0));
3980         actionList.add(ab.build());
3981
3982         ApplyActionsBuilder aab = new ApplyActionsBuilder();
3983         aab.setAction(actionList);
3984
3985         return ib;
3986     }
3987
3988     /**
3989      * Set Dst Arp MAC
3990      */
3991     private static InstructionBuilder createDstArpMacInstructions(InstructionBuilder ib, MacAddress macdst) {
3992
3993         List<Action> actionList = Lists.newArrayList();
3994         ActionBuilder ab = new ActionBuilder();
3995         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
3996
3997         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
3998         ArpTargetHardwareAddressBuilder arpdst = new ArpTargetHardwareAddressBuilder();
3999         arpdst.setAddress(macdst);
4000         setFieldBuilder.setLayer3Match(arpmatch.build());
4001         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
4002         ab.setKey(new ActionKey(0));
4003         actionList.add(ab.build());
4004
4005         ApplyActionsBuilder aab = new ApplyActionsBuilder();
4006         aab.setAction(actionList);
4007
4008         return ib;
4009     }
4010
4011     /**
4012      * Set Dst Arp IP
4013      */
4014     private static InstructionBuilder createDstArpIpInstructions(InstructionBuilder ib, Ipv4Prefix dstiparp) {
4015
4016         List<Action> actionList = Lists.newArrayList();
4017         ActionBuilder ab = new ActionBuilder();
4018         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
4019
4020         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
4021         arpmatch.setArpTargetTransportAddress(dstiparp);
4022         setFieldBuilder.setLayer3Match(arpmatch.build());
4023         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
4024         ab.setKey(new ActionKey(0));
4025         actionList.add(ab.build());
4026
4027         ApplyActionsBuilder aab = new ApplyActionsBuilder();
4028         aab.setAction(actionList);
4029
4030         return ib;
4031     }
4032
4033     /**
4034      * Set Src Arp IP
4035      */
4036     private static InstructionBuilder createSrcArpIpInstructions(InstructionBuilder ib, Ipv4Prefix srciparp) {
4037
4038         List<Action> actionList = Lists.newArrayList();
4039         ActionBuilder ab = new ActionBuilder();
4040         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
4041
4042         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
4043         arpmatch.setArpSourceTransportAddress(srciparp);
4044         setFieldBuilder.setLayer3Match(arpmatch.build());
4045         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
4046         ab.setKey(new ActionKey(0));
4047         actionList.add(ab.build());
4048
4049         ApplyActionsBuilder aab = new ApplyActionsBuilder();
4050         aab.setAction(actionList);
4051
4052         return ib;
4053     }
4054
4055     @Override
4056     public void initializeOFFlowRules(Node openflowNode) {
4057         Preconditions.checkNotNull(connectionService);
4058         List<Node> ovsNodes = connectionService.getNodes();
4059         if (ovsNodes == null) return;
4060         for (Node ovsNode : ovsNodes) {
4061             Long brIntDpid = this.getIntegrationBridgeOFDPID(ovsNode);
4062             Long brExDpid = this.getExternalBridgeDpid(ovsNode);
4063             logger.debug("Compare openflowNode to OVS node {} vs {} and {}", openflowNode.getID(), brIntDpid, brExDpid);
4064             String openflowID = openflowNode.getID().toString();
4065             if (openflowID.contains(brExDpid.toString())) {
4066                 this.initializeFlowRules(ovsNode, configurationService.getExternalBridgeName());
4067                 this.triggerInterfaceUpdates(ovsNode);
4068             }
4069             if (openflowID.contains(brIntDpid.toString())) {
4070                 this.initializeFlowRules(ovsNode, configurationService.getIntegrationBridgeName());
4071                 this.triggerInterfaceUpdates(ovsNode);
4072             }
4073         }
4074     }
4075
4076     private NodeBuilder createNodeBuilder(String nodeId) {
4077         NodeBuilder builder = new NodeBuilder();
4078         builder.setId(new NodeId(nodeId));
4079         builder.setKey(new NodeKey(builder.getId()));
4080         return builder;
4081     }
4082
4083     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder
4084                                                                                                                                              node) {
4085         return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
4086                 node.getKey()).toInstance();
4087     }
4088
4089     private String getInternalBridgeUUID (Node node, String bridgeName) {
4090         Preconditions.checkNotNull(ovsdbConfigurationService);
4091         try {
4092             Map<String, Row> bridgeTable = ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
4093             if (bridgeTable == null) return null;
4094             for (String key : bridgeTable.keySet()) {
4095                 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(key));
4096                 if (bridge.getName().equals(bridgeName)) return key;
4097             }
4098         } catch (Exception e) {
4099             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
4100         }
4101         return null;
4102     }
4103 }