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