Merge "BUG-2714 OVSDB needs to be more proactive in reporting errors with underlying...
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / netvirt / openstack / netvirt / providers / openflow13 / OF13Provider.java
1 /*
2  * Copyright (c) 2013, 2015 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.openstack.netvirt.providers.openflow13;
10
11 import java.net.InetAddress;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.concurrent.ExecutionException;
17
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
25 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
26 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
27 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
28 import org.opendaylight.netvirt.openstack.netvirt.MdsalHelper;
29 import org.opendaylight.netvirt.openstack.netvirt.NetworkHandler;
30 import org.opendaylight.netvirt.openstack.netvirt.api.BridgeConfigurationManager;
31 import org.opendaylight.netvirt.openstack.netvirt.api.ClassifierProvider;
32 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
33 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
34 import org.opendaylight.netvirt.openstack.netvirt.api.EgressAclProvider;
35 import org.opendaylight.netvirt.openstack.netvirt.api.IngressAclProvider;
36 import org.opendaylight.netvirt.openstack.netvirt.api.L2ForwardingProvider;
37 import org.opendaylight.netvirt.openstack.netvirt.api.NetworkingProvider;
38 import org.opendaylight.netvirt.openstack.netvirt.api.NetworkingProviderManager;
39 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheManager;
40 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
41 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
42 import org.opendaylight.netvirt.openstack.netvirt.api.Status;
43 import org.opendaylight.netvirt.openstack.netvirt.api.StatusCode;
44 import org.opendaylight.netvirt.openstack.netvirt.api.TenantNetworkManager;
45 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
46 import org.opendaylight.netvirt.openstack.netvirt.providers.NetvirtProvidersProvider;
47 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
48 import org.opendaylight.netvirt.utils.mdsal.openflow.InstructionUtils;
49 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
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.group.action._case.GroupActionBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
92 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
93 import org.osgi.framework.BundleContext;
94 import org.osgi.framework.ServiceReference;
95 import org.slf4j.Logger;
96 import org.slf4j.LoggerFactory;
97
98 import com.google.common.base.Optional;
99 import com.google.common.base.Preconditions;
100 import com.google.common.collect.Lists;
101 import com.google.common.collect.Maps;
102 import com.google.common.util.concurrent.CheckedFuture;
103
104
105 /**
106  * Open vSwitch OpenFlow 1.3 Networking Provider for OpenStack Neutron
107  *
108  * @author Madhu Venugopal
109  * @author Brent Salisbury
110  * @author Dave Tucker
111  * @author Sam Hague
112  */
113 // Methods' parameters in this class follow the same pattern to avoid confusion between same-typed parameters
114 // The patterns need to be preserved even though not all parameters are used in all methods
115 @SuppressWarnings("UnusedParameters")
116 public class OF13Provider implements ConfigInterface, NetworkingProvider {
117     private static final Logger LOG = LoggerFactory.getLogger(OF13Provider.class);
118     private static final short TABLE_0_DEFAULT_INGRESS = 0;
119     private static final short TABLE_1_ISOLATE_TENANT = 10;
120     private static final short TABLE_2_LOCAL_FORWARD = 20;
121     private static Long groupId = 1L;
122     private DataBroker dataBroker = null;
123
124     private volatile ConfigurationService configurationService;
125     private volatile BridgeConfigurationManager bridgeConfigurationManager;
126     private volatile TenantNetworkManager tenantNetworkManager;
127     private volatile SecurityServicesManager securityServicesManager;
128     private volatile ClassifierProvider classifierProvider;
129     private volatile IngressAclProvider ingressAclProvider;
130     private volatile EgressAclProvider egressAclProvider;
131     private volatile NodeCacheManager nodeCacheManager;
132     private volatile L2ForwardingProvider l2ForwardingProvider;
133
134     public static final String NAME = "OF13Provider";
135     private volatile BundleContext bundleContext;
136     private volatile Southbound southbound;
137
138     private Set<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId>
139                     intBridgesWithoutVmPorts = new HashSet<>();
140
141     public OF13Provider() {
142         this.dataBroker = NetvirtProvidersProvider.getDataBroker();
143     }
144
145     @Override
146     public String getName() {
147         return NAME;
148     }
149
150     @Override
151     public boolean supportsServices() {
152         return true;
153     }
154
155     @Override
156     public boolean hasPerTenantTunneling() {
157         return false;
158     }
159
160     // The method is tested for in OF13ProviderTest
161     @SuppressWarnings("unused")
162     private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
163         InetAddress srcTunnelEndPoint = configurationService.getTunnelEndPoint(node);
164         if (srcTunnelEndPoint == null) {
165             LOG.error("Tunnel Endpoint not configured for Node {}", node);
166             return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
167         }
168
169         if (!bridgeConfigurationManager.isNodeNeutronReady(node)) {
170             LOG.error("{} is not Overlay ready", node);
171             return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
172         }
173
174         if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
175             LOG.debug("{} has no VM corresponding to segment {}", node, tunnelKey);
176             return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey);
177         }
178         return new Status(StatusCode.SUCCESS);
179     }
180
181     private String getTunnelName(String tunnelType, InetAddress dst) {
182         return tunnelType+"-"+dst.getHostAddress();
183     }
184
185     private boolean addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
186         String tunnelBridgeName = configurationService.getIntegrationBridgeName();
187         String portName = getTunnelName(tunnelType, dst);
188         LOG.info("addTunnelPort enter: portName: {}", portName);
189         if (southbound.extractTerminationPointAugmentation(node, portName) != null
190                 || southbound.isTunnelTerminationPointExist(node, tunnelBridgeName, portName)) {
191             LOG.info("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node.getNodeId().getValue());
192             return true;
193         }
194
195         Map<String, String> options = Maps.newHashMap();
196         options.put("key", "flow");
197         options.put("local_ip", src.getHostAddress());
198         options.put("remote_ip", dst.getHostAddress());
199
200         if (!southbound.addTunnelTerminationPoint(node, tunnelBridgeName, portName, tunnelType, options)) {
201             LOG.error("Failed to insert Tunnel port {} in {}", portName, tunnelBridgeName);
202             return false;
203         }
204
205             LOG.info("addTunnelPort exit: portName: {}", portName);
206         return true;
207     }
208
209     /* delete port from ovsdb port table */
210     private boolean deletePort(Node node, String bridgeName, String portName) {
211         // TODO SB_MIGRATION
212         // might need to convert from ovsdb node to bridge node
213         return southbound.deleteTerminationPoint(node, portName);
214     }
215
216     private boolean deleteTunnelPort(Node node, String tunnelType, InetAddress src, InetAddress dst) {
217         String tunnelBridgeName = configurationService.getIntegrationBridgeName();
218         String portName = getTunnelName(tunnelType, dst);
219         return deletePort(node, tunnelBridgeName, portName);
220     }
221
222     private boolean deletePhysicalPort(Node node, String phyIntfName) {
223         String intBridgeName = configurationService.getIntegrationBridgeName();
224         return deletePort(node, intBridgeName, phyIntfName);
225     }
226
227     private void programLocalBridgeRules(Node node, Long dpid, String segmentationId,
228                                          String attachedMac, long localPort) {
229         /*
230          * Table(0) Rule #3
231          * ----------------
232          * Match: VM sMac and Local Ingress Port
233          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
234          */
235
236         handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT,
237                 segmentationId, localPort, attachedMac, true);
238
239         /*
240          * Table(0) Rule #4
241          * ----------------
242          * Match: Drop any remaining Ingress Local VM Packets
243          * Action: Drop w/ a low priority
244          */
245
246         handleDropSrcIface(dpid, localPort, true);
247
248         /*
249          * Table(2) Rule #1
250          * ----------------
251          * Match: Match TunID and Destination DL/dMAC Addr
252          * Action: Output Port
253          * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
254          */
255
256         handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, true);
257
258         /*
259          * Table(2) Rule #2
260          * ----------------
261          * Match: Tunnel ID and dMAC (::::FF:FF)
262          * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
263          * actions=output:2,3,4,5
264          */
265
266         handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
267         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
268
269         /*
270          * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
271          */
272         /*
273          * Table(1) Rule #3
274          * ----------------
275          * Match:  Any remaining Ingress Local VM Packets
276          * Action: Drop w/ a low priority
277          * -------------------------------------------
278          * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
279          */
280
281         handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, true);
282
283         /*
284          * Table(2) Rule #3
285          * ----------------
286          * Match: Any Remaining Flows w/a TunID
287          * Action: Drop w/ a low priority
288          * table=2,priority=8192,tun_id=0x5 actions=drop
289          */
290
291         handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, true);
292     }
293
294     private void removeLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
295         /*
296          * Table(0) Rule #3
297          * ----------------
298          * Match: VM sMac and Local Ingress Port
299          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
300          */
301
302         handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, false);
303
304         /*
305          * Table(0) Rule #4
306          * ----------------
307          * Match: Drop any remaining Ingress Local VM Packets
308          * Action: Drop w/ a low priority
309          */
310
311         handleDropSrcIface(dpid, localPort, false);
312
313         /*
314          * Table(2) Rule #1
315          * ----------------
316          * Match: Match TunID and Destination DL/dMAC Addr
317          * Action: Output Port
318          * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
319          */
320
321         handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, false);
322
323         /*
324          * Table(2) Rule #2
325          * ----------------
326          * Match: Tunnel ID and dMAC (::::FF:FF)
327          * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
328          * actions=output:2,3,4,5
329          */
330
331         handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
332         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
333     }
334
335     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
336         /*
337          * Table(0) Rule #2
338          * ----------------
339          * Match: Ingress Port, Tunnel ID
340          * Action: GOTO Local Table (20)
341          */
342
343         handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
344
345         /*
346          * Table(1) Rule #2
347          * ----------------
348          * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
349          * Action: Flood to selected destination TEPs
350          * -------------------------------------------
351          * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
352          * actions=output:10,output:11,goto_table:2
353          */
354
355         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
356
357     }
358
359     private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
360         /*
361          * Table(1) Rule #1
362          * ----------------
363          * Match: Drop any remaining Ingress Local VM Packets
364          * Action: Drop w/ a low priority
365          * -------------------------------------------
366          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
367          * actions=output:11,goto_table:2
368          */
369
370         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, true);
371     }
372
373     private void removeRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
374         /*
375          * Table(1) Rule #1
376          * ----------------
377          * Match: Drop any remaining Ingress Local VM Packets
378          * Action: Drop w/ a low priority
379          * -------------------------------------------
380          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
381          * actions=output:11,goto_table:2
382          */
383
384         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, false);
385     }
386
387     /* Remove tunnel rules if last node in this tenant network */
388     private void removePerTunnelRules(Node node, Long dpid, String segmentationId, long tunnelOFPort) {
389         /*
390          * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
391          */
392         /*
393          * Table(1) Rule #3
394          * ----------------
395          * Match:  Any remaining Ingress Local VM Packets
396          * Action: Drop w/ a low priority
397          * -------------------------------------------
398          * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
399          */
400
401         handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, false);
402
403         /*
404          * Table(2) Rule #3
405          * ----------------
406          * Match: Any Remaining Flows w/a TunID
407          * Action: Drop w/ a low priority
408          * table=2,priority=8192,tun_id=0x5 actions=drop
409          */
410
411         handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
412
413         /*
414          * Table(0) Rule #2
415          * ----------------
416          * Match: Ingress Port, Tunnel ID
417          * Action: GOTO Local Table (10)
418          */
419
420         handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
421
422         /*
423          * Table(1) Rule #2
424          * ----------------
425          * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
426          * Action: Flood to selected destination TEPs
427          * -------------------------------------------
428          * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
429          * actions=output:10,output:11,goto_table:2
430          */
431
432         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
433     }
434
435     private void programLocalVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
436         /*
437          * Table(0) Rule #1
438          * ----------------
439          * Tag traffic coming from the local port and vm srcmac
440          * Match: VM sMac and Local Ingress Port
441          * Action: Set VLAN ID and GOTO Local Table 1
442          */
443
444         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
445                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
446                 attachedMac, true);
447
448         /*
449          * Table(0) Rule #3
450          * ----------------
451          * Drop all other traffic coming from the local port
452          * Match: Drop any remaining Ingress Local VM Packets
453          * Action: Drop w/ a low priority
454          */
455
456         handleDropSrcIface(dpid, localPort, true);
457
458         /*
459          * Table(2) Rule #1
460          * ----------------
461          * Forward unicast traffic destined to the local port after stripping tag
462          * Match: Match VLAN ID and Destination DL/dMAC Addr
463          * Action: strip vlan, output to local port
464          * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
465          */
466
467         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
468                 localPort, attachedMac, true);
469
470         /*
471          * Table(2) Rule #2
472          * ----------------
473          * Match: VLAN ID and dMAC (::::FF:FF)
474          * Action: strip vlan, output to all local ports in this vlan
475          * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
476          * actions= strip_vlan, output:2,3,4,5
477          */
478
479         //handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
480         //        localPort, ethPort, true);
481         //handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
482         //        segmentationId, localPort, ethport, true);
483
484         /*
485          * Table(2) Rule #3
486          * ----------------
487          * Match: Any Remaining Flows w/a VLAN ID
488          * Action: Drop w/ a low priority
489          * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
490          */
491
492         //handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
493         //        true);
494     }
495
496     private void removeLocalVlanRules(Node node, Long dpid,
497                                       String segmentationId, String attachedMac, long localPort) {
498         /*
499          * Table(0) Rule #1
500          * ----------------
501          * Match: VM sMac and Local Ingress Port
502          * Action: Set VLAN ID and GOTO Local Table 1
503          */
504
505         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
506                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
507                 attachedMac, false);
508
509         /*
510          * Table(0) Rule #3
511          * ----------------
512          * Match: Drop any remaining Ingress Local VM Packets
513          * Action: Drop w/ a low priority
514          */
515
516         handleDropSrcIface(dpid, localPort, false);
517
518         /*
519          * Table(2) Rule #1
520          * ----------------
521          * Match: Match VLAN ID and Destination DL/dMAC Addr
522          * Action: strip vlan, output to local port
523          * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
524          */
525
526         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
527                 localPort, attachedMac, false);
528
529         /*
530          * Table(2) Rule #2
531          * ----------------
532          * Match: VLAN ID and dMAC (::::FF:FF)
533          * Action: strip vlan, output to all local ports in this vlan
534          * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
535          * actions= strip_vlan, output:2,3,4,5
536          */
537
538         //handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
539         //        localPort, ethPort, false);
540         //handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
541         //        segmentationId, localPort, false);
542
543     }
544
545     private void programLocalIngressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac,
546                                               long localPort, long ethPort) {
547         /*
548          * Table(0) Rule #2
549          * ----------------
550          * Match: Ingress port = physical interface, Vlan ID
551          * Action: GOTO Local Table 2
552          */
553
554         handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
555                 segmentationId, ethPort, true);
556
557         /*
558          * Table(1) Rule #2
559          * ----------------
560          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
561          * Action: Flood to local and remote VLAN members
562          * -------------------------------------------
563          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
564          * actions=output:10 (eth port),goto_table:2
565          * table=110, priority=16384,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
566          */
567
568         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, ethPort, true);
569
570         /*
571          * Table(1) Rule #2
572          * ----------------
573          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
574          * Action: Flood to local and remote VLAN members
575          * -------------------------------------------
576          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
577          * actions=output:10 (eth port),goto_table:2
578          */
579
580         //handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
581         //        segmentationId, ethPort, true);
582     }
583
584     private void programRemoteEgressVlanRules(Node node, Long dpid, String segmentationId,
585                                               String attachedMac, long ethPort) {
586         /*
587          * Table(1) Rule #1
588          * ----------------
589          * Match: Destination MAC is local VM MAC and vlan id
590          * Action: go to table 2
591          * -------------------------------------------
592          * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
593          * actions=goto_table:2
594          */
595
596         //handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
597         //        segmentationId, ethPort, attachedMac, true);
598
599         /*
600          * Table(1) Rule #3
601          * ----------------
602          * Match:  VLAN ID
603          * Action: Go to table 2
604          * -------------------------------------------
605          * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
606          * table=110,priority=8192,dl_vlan=2001 actions=output:2
607          */
608
609         handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, ethPort, true);
610     }
611
612     private void removeRemoteEgressVlanRules(Node node, Long dpid, String segmentationId,
613                                              String attachedMac, long localPort, long ethPort) {
614         /*
615          * Table(1) Rule #1
616          * ----------------
617          * Match: Destination MAC is local VM MAC and vlan id
618          * Action: go to table 2
619          * -------------------------------------------
620          * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
621          * actions=goto_table:2
622          */
623
624         //handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
625         //        segmentationId, ethPort, attachedMac, false);
626
627         /*
628          * Table(1) Rule #2
629          * ----------------
630          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
631          * Action: Flood to local and remote VLAN members
632          * -------------------------------------------
633          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
634          * actions=output:10 (eth port),goto_table:2
635          * table=110, priority=16384,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
636          */
637
638         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, ethPort, false);
639     }
640
641     private void removePerVlanRules(Node node, Long dpid, String segmentationId, long localPort, long ethPort) {
642         /*
643          * Table(2) Rule #3
644          * ----------------
645          * Match: Any Remaining Flows w/a VLAN ID
646          * Action: Drop w/ a low priority
647          * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
648          */
649
650         //handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
651
652         /*
653          * Table(0) Rule #2
654          * ----------------
655          * Match: Ingress port = physical interface, Vlan ID
656          * Action: GOTO Local Table 2
657          */
658
659         handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, ethPort, false);
660
661         /*
662          * Table(1) Rule #2
663          * ----------------
664          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
665          * Action: Flood to local and remote VLAN members
666          * -------------------------------------------
667          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
668          * actions=output:10 (eth port),goto_table:2
669          * table=110, priority=16384,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
670          */
671
672         //handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, ethPort, false);
673
674         /*
675          * Table(1) Rule #2
676          * ----------------
677          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
678          * Action: Flood to local and remote VLAN members
679          * -------------------------------------------
680          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
681          * actions=output:10 (eth port),goto_table:2
682          */
683
684         //handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
685         //        segmentationId, ethPort, false);
686
687         /*
688          * Table(1) Rule #3
689          * ----------------
690          * Match:  VLAN ID
691          * Action: Go to table 2
692          * -------------------------------------------
693          * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
694          * table=110,priority=8192,dl_vlan=2001 actions=output:2
695          */
696
697         handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, ethPort, false);
698     }
699
700     private long getDpid(Node node) {
701         long dpid = southbound.getDataPathId(node);
702         if (dpid == 0) {
703             LOG.warn("getDpid: dpid not found: {}", node);
704         }
705         return dpid;
706     }
707
708     private long getIntegrationBridgeOFDPID(Node node) {
709         long dpid = 0L;
710         if (southbound.getBridgeName(node).equals(configurationService.getIntegrationBridgeName())) {
711             dpid = getDpid(node);
712         }
713         return dpid;
714     }
715
716     /**
717      * Returns true is the network if of type GRE or VXLAN
718      *
719      * @param networkType The type of the network
720      * @return returns true if the network is a tunnel
721      */
722     private boolean isTunnel(String networkType)
723     {
724         return (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || networkType.equalsIgnoreCase
725                 (NetworkHandler.NETWORK_TYPE_VXLAN));
726     }
727
728     /**
729      * Returns true if the network is of type vlan.
730      *
731      * @param networkType The type of the network
732      * @return returns true if the network is a vlan
733      */
734     private boolean isVlan(String networkType)
735     {
736         return networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN);
737     }
738
739     private void programLocalRules(String networkType, String segmentationId, Node node,
740                                     OvsdbTerminationPointAugmentation intf) {
741         LOG.debug("programLocalRules: node: {}, intf: {}, networkType: {}, segmentationId: {}",
742                 node.getNodeId(), intf.getName(), networkType, segmentationId);
743         try {
744             long dpid = getIntegrationBridgeOFDPID(node);
745             if (dpid == 0L) {
746                 LOG.debug("programLocalRules: Openflow Datapath-ID not set for the integration bridge in {}",
747                         node);
748                 return;
749             }
750
751             long localPort = southbound.getOFPort(intf);
752             if (localPort == 0) {
753                 LOG.info("programLocalRules: could not find ofPort for Port {} on Node {}",
754                          intf.getName(), node.getNodeId());
755                 return;
756             }
757
758             String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
759             if (attachedMac == null) {
760                 LOG.warn("No AttachedMac seen in {}", intf);
761                 return;
762             }
763
764             /* Program local rules based on network type */
765             if (isVlan(networkType)) {
766                 LOG.debug("Program local vlan rules for interface {}", intf.getName());
767                 programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
768             }
769             if ((isTunnel(networkType) || isVlan(networkType))) {
770                 programLocalSecurityGroupRules(attachedMac, node, intf, dpid, localPort, segmentationId, true);
771             }
772             if (isTunnel(networkType)) {
773                 LOG.debug("Program local bridge rules for interface {}, "
774                                 + "dpid: {}, segmentationId: {}, attachedMac: {}, localPort: {}",
775                         intf.getName(), dpid, segmentationId, attachedMac, localPort);
776                 programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
777             }
778         } catch (Exception e) {
779             LOG.error("Exception in programming Local Rules for {} on {}", intf, node, e);
780         }
781     }
782
783     private void removeLocalRules(String networkType, String segmentationId, Node node,
784                                    OvsdbTerminationPointAugmentation intf) {
785         LOG.debug("removeLocalRules: node: {}, intf: {}, networkType: {}, segmentationId: {}",
786                 node.getNodeId(), intf.getName(), networkType, segmentationId);
787         try {
788             long dpid = getIntegrationBridgeOFDPID(node);
789             if (dpid == 0L) {
790                 LOG.debug("removeLocalRules: Openflow Datapath-ID not set for the integration bridge in {}", node);
791                 return;
792             }
793
794             long localPort = southbound.getOFPort(intf);
795             if (localPort == 0) {
796                 LOG.info("removeLocalRules: could not find ofPort");
797                 return;
798             }
799
800             String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
801             if (attachedMac == null) {
802                 LOG.warn("No AttachedMac seen in {}", intf);
803                 return;
804             }
805
806             /* Program local rules based on network type */
807             if (isVlan(networkType)) {
808                 LOG.debug("Remove local vlan rules for interface {}", intf.getName());
809                 removeLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
810             } else if (isTunnel(networkType)) {
811                 LOG.debug("Remove local bridge rules for interface {}", intf.getName());
812                 removeLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
813             }
814             if (isTunnel(networkType) || isVlan(networkType)) {
815                 programLocalSecurityGroupRules(attachedMac, node, intf, dpid, localPort, segmentationId, false);
816             }
817         } catch (Exception e) {
818             LOG.error("Exception in removing Local Rules for {} on {}", intf, node, e);
819         }
820     }
821
822     private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
823                                      OvsdbTerminationPointAugmentation intf, boolean local) {
824         LOG.debug("programTunnelRules: node: {}, intf: {}, local: {}, tunnelType: {}, "
825                         + "segmentationId: {}, dstAddr: {}",
826                 node.getNodeId(), intf.getName(), local, tunnelType, segmentationId, dst.getHostAddress());
827         try {
828             long dpid = getIntegrationBridgeOFDPID(node);
829             if (dpid == 0L) {
830                 LOG.debug("programTunnelRules: Openflow Datapath-ID not set for the integration bridge in {}", node);
831                 return;
832             }
833
834             long localPort = southbound.getOFPort(intf);
835             if (localPort == 0) {
836                 LOG.info("programTunnelRules: could not find ofPort for Port {} on Node{}", intf.getName(), node.getNodeId());
837                 return;
838             }
839
840             String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
841             if (attachedMac == null) {
842                 LOG.warn("programTunnelRules: No AttachedMac seen in {}", intf);
843                 return;
844             }
845
846             OvsdbTerminationPointAugmentation tunnelPort= southbound.getTerminationPointOfBridge(node, getTunnelName(tunnelType, dst));
847             if (tunnelPort != null){
848                 long tunnelOFPort = southbound.getOFPort(tunnelPort);
849                 if (tunnelOFPort == 0) {
850                     LOG.error("programTunnelRules: Could not Identify Tunnel port {} -> OF ({}) on {}",
851                             tunnelPort.getName(), tunnelOFPort, node);
852                     return;
853                 }
854                 LOG.debug("programTunnelRules: Identified Tunnel port {} -> OF ({}) on {}",
855                         tunnelPort.getName(), tunnelOFPort, node);
856
857                 if (!local) {
858                     LOG.trace("programTunnelRules: program remote egress tunnel rules: node {}, intf {}",
859                             node.getNodeId().getValue(), intf.getName());
860                     programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac,
861                             tunnelOFPort, localPort);
862                 } else {
863                     LOG.trace("programTunnelRules: program local ingress tunnel rules: node {}, intf {}",
864                             node.getNodeId().getValue(), intf.getName());
865                     programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac,
866                             tunnelOFPort, localPort);
867                 }
868             }
869         } catch (Exception e) {
870             LOG.warn("Failed to program tunnel rules, node {}, intf {}", node, intf, e);
871         }
872     }
873
874     private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
875                                     OvsdbTerminationPointAugmentation intf,
876                                     boolean local, boolean isLastInstanceOnNode) {
877         LOG.debug("removeTunnelRules: node: {}, intf: {}, local: {}, tunnelType: {}, "
878                         + "segmentationId: {}, dstAddr: {}, isLastinstanceOnNode: {}",
879                 node.getNodeId(), intf.getName(), local, tunnelType, segmentationId, dst, isLastInstanceOnNode);
880         try {
881             long dpid = getIntegrationBridgeOFDPID(node);
882             if (dpid == 0L) {
883                 LOG.debug("removeTunnelRules: Openflow Datapath-ID not set for the integration bridge in {}", node);
884                 return;
885             }
886
887             long localPort = southbound.getOFPort(intf);
888             if (localPort == 0) {
889                 LOG.info("removeTunnelRules: could not find ofPort");
890                 return;
891             }
892
893             String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
894             if (attachedMac == null) {
895                 LOG.error("removeTunnelRules: No AttachedMac seen in {}", intf);
896                 return;
897             }
898
899             List<OvsdbTerminationPointAugmentation> intfs = southbound.getTerminationPointsOfBridge(node);
900             for (OvsdbTerminationPointAugmentation tunIntf : intfs) {
901                 if (tunIntf.getName().equals(getTunnelName(tunnelType, dst))) {
902                     long tunnelOFPort = southbound.getOFPort(tunIntf);
903                     if (tunnelOFPort == 0) {
904                         LOG.error("Could not Identify Tunnel port {} -> OF ({}) on {}",
905                                 tunIntf.getName(), tunnelOFPort, node);
906                         return;
907                     }
908                     LOG.debug("Identified Tunnel port {} -> OF ({}) on {}",
909                             tunIntf.getName(), tunnelOFPort, node);
910
911                     if (!local) {
912                         removeRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac,
913                                 tunnelOFPort, localPort);
914                     }
915                     if (local && isLastInstanceOnNode) {
916                         removePerTunnelRules(node, dpid, segmentationId, tunnelOFPort);
917                     }
918                     return;
919                 }
920             }
921         } catch (Exception e) {
922             LOG.error("Failed to remove tunnel rules, node {}, intf {}", node, intf, e);
923         }
924     }
925
926     private void programVlanRules (NeutronNetwork network, Node node, OvsdbTerminationPointAugmentation intf) {
927         LOG.debug("programVlanRules: node: {}, network: {}, intf: {}",
928                 node.getNodeId(), network.getNetworkUUID(), intf.getName());
929         long dpid = getIntegrationBridgeOFDPID(node);
930         if (dpid == 0L) {
931             LOG.debug("programVlanRules: Openflow Datapath-ID not set for the integration bridge in {}", node);
932             return;
933         }
934
935         long localPort = southbound.getOFPort(intf);
936         if (localPort == 0) {
937             LOG.debug("programVlanRules: could not find ofPort for {}", intf.getName());
938             return;
939         }
940
941         String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
942         if (attachedMac == null) {
943             LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
944             return;
945         }
946
947         String phyIfName =
948                 bridgeConfigurationManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
949         long ethOFPort = southbound.getOFPort(node, phyIfName);
950         if (ethOFPort == 0) {
951             LOG.warn("programVlanRules: could not find ofPort for physical port {}", phyIfName);
952             return;
953         }
954         LOG.debug("programVlanRules: Identified eth port {} -> ofPort ({}) on {}",
955                 phyIfName, ethOFPort, node);
956         // TODO: add logic to only add rule on remote nodes
957         programRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(),
958                 attachedMac, ethOFPort);
959         programLocalIngressVlanRules(node, dpid, network.getProviderSegmentationID(),
960                 attachedMac, localPort, ethOFPort);
961     }
962
963     private void removeVlanRules (NeutronNetwork network, Node node, OvsdbTerminationPointAugmentation intf,
964                                   boolean isLastInstanceOnNode) {
965         LOG.debug("removeVlanRules: node: {}, network: {}, intf: {}, isLastInstanceOnNode",
966                 node.getNodeId(), network.getNetworkUUID(), intf.getName(), isLastInstanceOnNode);
967         long dpid = getIntegrationBridgeOFDPID(node);
968         if (dpid == 0L) {
969             LOG.debug("removeVlanRules: Openflow Datapath-ID not set for the integration bridge in {}", node);
970             return;
971         }
972
973         long localPort = southbound.getOFPort(intf);
974         if (localPort == 0) {
975             LOG.debug("removeVlanRules: programVlanRules: could not find ofPort for {}", intf.getName());
976             return;
977         }
978
979         String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
980         if (attachedMac == null) {
981             LOG.debug("removeVlanRules: No AttachedMac seen in {}", intf);
982             return;
983         }
984
985         String phyIfName =
986                 bridgeConfigurationManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
987         long ethOFPort = southbound.getOFPort(node, phyIfName);
988         if (ethOFPort == 0) {
989             LOG.warn("removeVlanRules: could not find ofPort for physical port {}", phyIfName);
990             return;
991         }
992         LOG.debug("removeVlanRules: Identified eth port {} -> ofPort ({}) on {}",
993                 phyIfName, ethOFPort, node);
994
995         removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(),
996                 attachedMac, localPort, ethOFPort);
997         if (isLastInstanceOnNode) {
998             removePerVlanRules(node, dpid, network.getProviderSegmentationID(), localPort, ethOFPort);
999         }
1000     }
1001
1002     private void programLocalSecurityGroupRules(String attachedMac, Node node, OvsdbTerminationPointAugmentation intf,
1003                                                 Long dpid,long localPort, String segmentationId,
1004                                                 boolean write) {
1005
1006         LOG.debug("programLocalRules: Program fixed security group rules for interface {}", intf.getName());
1007         boolean isPortSecurityEnabled = securityServicesManager.isPortSecurityEnabled(intf);
1008         if (!isPortSecurityEnabled) {
1009             LOG.info("Port security is not enabled" + intf);
1010             return;
1011         }
1012         NeutronPort dhcpPort = securityServicesManager.getDhcpServerPort(intf);
1013         List<Neutron_IPs> srcAddressList = null;
1014         if (null != dhcpPort) {
1015             srcAddressList = securityServicesManager.getIpAddressList(intf);
1016             if (null == srcAddressList) {
1017                 LOG.warn("programLocalRules: No Ip address assigned {}", intf);
1018                 return;
1019             }
1020             ingressAclProvider.programFixedSecurityGroup(dpid, segmentationId, dhcpPort.getMacAddress(), localPort,
1021                                                          attachedMac, write);
1022             egressAclProvider.programFixedSecurityGroup(dpid, segmentationId, attachedMac, localPort,
1023                                                         srcAddressList, write);
1024             /* If the network type is tunnel based (VXLAN/GRRE/etc) with Neutron Port Security ACLs */
1025             /* TODO SB_MIGRATION */
1026
1027             LOG.debug("Neutron port has a Port Security Group");
1028             // Retrieve the security group from the Neutron Port and apply the rules
1029             List<NeutronSecurityGroup> securityGroupListInPort = securityServicesManager
1030                     .getSecurityGroupInPortList(intf);
1031             String neutronPortId = southbound.getInterfaceExternalIdsValue(intf,
1032                                                                            Constants.EXTERNAL_ID_INTERFACE_ID);
1033             for (NeutronSecurityGroup securityGroupInPort:securityGroupListInPort) {
1034                 ingressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
1035                                                             securityGroupInPort, neutronPortId, write);
1036                 egressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
1037                                                            securityGroupInPort, neutronPortId, write);
1038             }
1039
1040         } else {
1041             LOG.warn("programLocalRules: No DCHP port seen in  network of {}", intf);
1042         }
1043     }
1044
1045     /*
1046      * The function is for the new compute node joining the existing network.
1047      * When a new VM is instantiated in the new compute node, neutron port add
1048      * event is generated. This event is processed only for that node. So,
1049      * loop through all the ports of the same network and install unicast mac
1050      * flow for the VM's created on the TEP of the destination node in src node.
1051      * This function will be executed even for any new VM creation in an existing
1052      * network. If a cache is maintained to optimize the below flow addition, it will
1053      * work only for one unstack and restack. For the next unstack and restack,
1054      * it will not work since the cache would have been already deleted.
1055      */
1056     private void programTunnelRulesInNewNode(NeutronNetwork network,
1057                                              String networkType, String segmentationId,
1058                                              InetAddress src, InetAddress dst,
1059                                              Node srcBridgeNode, Node dstBridgeNode,
1060                                              OvsdbTerminationPointAugmentation intf){
1061         LOG.debug("programTunnelRulesInNewNode: network {} networkType {} segId {} src {} dst {} srcBridgeNode {} dstBridgeNode {} intf {}",
1062                     network.getNetworkName(), networkType, segmentationId, src.getHostAddress(),
1063                     dst.getHostAddress(), srcBridgeNode, dstBridgeNode, intf);
1064         try {
1065             long localPort = southbound.getOFPort(intf);
1066             if (localPort != 0)
1067             {
1068                 LOG.debug("Interface update details {}", intf);
1069
1070                 /*
1071                  * When a network is added and the TEP destination is not present in a
1072                  * node C1, tunnelin and broadcast rules will not be programmed, since
1073                  * OF port is not created. So, when a new node C2 joins and create a new
1074                  * VM, the tunnelin and broadcast rule will not be present in C1.
1075                  * So, handling it in the case below to make ping work.
1076                  */
1077                 if (securityServicesManager.getNeutronPortFromDhcpIntf(intf) == null){
1078                     programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, true);
1079                 }
1080
1081                 /*
1082                  * FIX for 4208 - loop through all the ports and add the VM's
1083                  * unicast mac rule of the destination node in the source node.
1084                  * When a new node is added, it needs to configure the VM unicast mac
1085                  * flow rules which were created before it was joined to an existing
1086                  * network.
1087                  */
1088                 List<OvsdbTerminationPointAugmentation> ports = southbound.getTerminationPointsOfBridge(dstBridgeNode);
1089                 for (OvsdbTerminationPointAugmentation port : ports) {
1090
1091                     NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(port);
1092                     if (neutronNetwork != null) {
1093                         String netType = neutronNetwork.getProviderNetworkType();
1094                         String segId = neutronNetwork.getProviderSegmentationID();
1095                         InetAddress dstAddr = configurationService.getTunnelEndPoint(dstBridgeNode);
1096
1097                         if (segId != null && netType != null && dstAddr != null) {
1098                             programTunnelRules(netType, segId, dstAddr, srcBridgeNode, port, false);
1099                         }
1100                     }
1101
1102                     if (network == tenantNetworkManager.getTenantNetwork(port)){
1103                         programTunnelRules(networkType, segmentationId, dst, srcBridgeNode, port, false);
1104                     }
1105                     else{
1106                         LOG.trace("Port {} is not part of network {}", port, network);
1107                     }
1108                 }
1109             }
1110         } catch (Exception e) {
1111             LOG.error("Exception during handlingNeutron network add", e);
1112         }
1113     }
1114
1115     private boolean bridgeHasVmPort(Node bridgeNode) {
1116         String intBridgeName = configurationService.getIntegrationBridgeName();
1117         String extBridgeName = configurationService.getExternalBridgeName();
1118         List<TerminationPoint> terminationPoints = bridgeNode.getTerminationPoint();
1119         if (terminationPoints == null) return false;
1120
1121         for (TerminationPoint tp : terminationPoints) {
1122             String tpName = tp.getTpId().getValue();
1123             if (tpName != null && !tpName.equals(intBridgeName) && !tpName.equals(extBridgeName)) {
1124                 OvsdbTerminationPointAugmentation tpAug = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
1125                 if (tpAug != null && southbound.getOFPort(tpAug) != 0) {
1126                     return true;
1127                 }
1128             }
1129         }
1130
1131         return false;
1132     }
1133
1134     @Override
1135     public boolean handleInterfaceUpdate(NeutronNetwork network, Node srcNode, OvsdbTerminationPointAugmentation intf) {
1136         LOG.debug("handleInterfaceUpdate: network: {} srcNode: {}, intf: {}",
1137                     network.getProviderSegmentationID(), srcNode.getNodeId(), intf.getName());
1138         Preconditions.checkNotNull(nodeCacheManager);
1139
1140         org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId srcNodeId =
1141                 srcNode.getNodeId();
1142         Map<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId,Node> nodes =
1143                 nodeCacheManager.getOvsdbNodes();
1144
1145         nodes.remove(southbound.extractBridgeOvsdbNodeId(srcNode));
1146         String networkType = network.getProviderNetworkType();
1147         String segmentationId = network.getProviderSegmentationID();
1148         Node srcBridgeNode = southbound.getBridgeNode(srcNode, configurationService.getIntegrationBridgeName());
1149
1150         programLocalRules(networkType, network.getProviderSegmentationID(), srcBridgeNode, intf);
1151
1152         if (isVlan(networkType)) {
1153             programVlanRules(network, srcNode, intf);
1154         } else if (isTunnel(networkType)){
1155
1156             boolean sourceTunnelStatus = false;
1157             boolean destTunnelStatus = false;
1158             boolean isSrcinNw = tenantNetworkManager.isTenantNetworkPresentInNode(srcBridgeNode, segmentationId);
1159             for (Node dstNode : nodes.values()) {
1160                 InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1161                 InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1162                 if ((src != null) && (dst != null)) {
1163                     sourceTunnelStatus = addTunnelPort(srcBridgeNode, networkType, src, dst);
1164
1165                     Node dstBridgeNode = southbound.getBridgeNode(dstNode,
1166                             configurationService.getIntegrationBridgeName());
1167
1168                     if (dstBridgeNode != null) {
1169                         destTunnelStatus = addTunnelPort(dstBridgeNode, networkType, dst, src);
1170                     }
1171
1172                     if (sourceTunnelStatus) {
1173                         boolean isDestinNw = tenantNetworkManager.isTenantNetworkPresentInNode(dstBridgeNode, segmentationId);
1174                         //Check whether the network is present in src & dst node
1175                         //If only present , add vxlan ports in TunnelRules for both nodes (bug# 5614)
1176                         if (isSrcinNw && isDestinNw) {
1177                             programTunnelRules(networkType, segmentationId, dst, srcBridgeNode, intf, true);
1178                             programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, true);
1179                         }
1180                     }
1181                     if (destTunnelStatus) {
1182                         programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, false);
1183
1184                         if (srcNodeId != null && intBridgesWithoutVmPorts.contains(srcNodeId)) {
1185                             programTunnelRulesInNewNode(network, networkType, segmentationId, src, dst,
1186                                     srcBridgeNode, dstBridgeNode, intf);
1187                             intBridgesWithoutVmPorts.remove(srcNodeId);
1188                         }
1189                     }
1190                 } else {
1191                     LOG.warn("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table. "
1192                                     + "Check source {} or destination {}",
1193                             src != null ? src.getHostAddress() : "null",
1194                             dst != null ? dst.getHostAddress() : "null");
1195                 }
1196             }
1197         }
1198
1199         if (srcNodeId != null && !bridgeHasVmPort(srcNode)) {
1200             intBridgesWithoutVmPorts.add(srcNodeId);
1201         }
1202
1203         return true;
1204     }
1205
1206     private void triggerInterfaceUpdates(Node node) {
1207         LOG.debug("enter triggerInterfaceUpdates for {}", node.getNodeId());
1208         List<OvsdbTerminationPointAugmentation> ports = southbound.extractTerminationPointAugmentations(node);
1209         if (ports != null && !ports.isEmpty()) {
1210             for (OvsdbTerminationPointAugmentation port : ports) {
1211                 NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(port);
1212                 if (neutronNetwork != null) {
1213                     LOG.warn("Trigger Interface update for {}", port);
1214                     handleInterfaceUpdate(neutronNetwork, node, port);
1215                 }
1216             }
1217         } else {
1218             LOG.warn("triggerInterfaceUpdates: tps are null");
1219         }
1220         LOG.debug("exit triggerInterfaceUpdates for {}", node.getNodeId());
1221     }
1222
1223     @Override
1224     public boolean handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode,
1225                                          OvsdbTerminationPointAugmentation intf, boolean isLastInstanceOnNode) {
1226         Map<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId,Node> nodes =
1227                 nodeCacheManager.getOvsdbNodes();
1228         nodes.remove(southbound.extractBridgeOvsdbNodeId(srcNode));
1229
1230         LOG.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
1231         String segmentationId = network.getProviderSegmentationID();
1232         List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(srcNode);
1233         if (southbound.isTunnel(intf)) {
1234             // Delete tunnel port
1235             try {
1236                 InetAddress src = InetAddress.getByName(
1237                         southbound.getOptionsValue(intf.getOptions(), "local_ip"));
1238                 InetAddress dst = InetAddress.getByName(
1239                         southbound.getOptionsValue(intf.getOptions(), "remote_ip"));
1240                 deleteTunnelPort(srcNode,
1241                         MdsalHelper.createOvsdbInterfaceType(intf.getInterfaceType()),
1242                         src, dst);
1243             } catch (Exception e) {
1244                 LOG.error("handleInterfaceDelete: failed to delete tunnel port", e);
1245             }
1246         } else if (phyIfName.contains(intf.getName())) {
1247             deletePhysicalPort(srcNode, intf.getName());
1248         } else {
1249             // delete all other interfaces
1250             removeLocalRules(network.getProviderNetworkType(), segmentationId,
1251                     srcNode, intf);
1252
1253             if (isVlan(network.getProviderNetworkType())) {
1254                 removeVlanRules(network, srcNode, intf, isLastInstanceOnNode);
1255             } else if (isTunnel(network.getProviderNetworkType())) {
1256
1257                 Node srcBridgeNode = southbound.getBridgeNode(srcNode, configurationService.getIntegrationBridgeName());
1258                 for (Node dstNode : nodes.values()) {
1259                     InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1260                     InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1261                     if ((src != null) && (dst != null)) {
1262                         LOG.info("Remove tunnel rules for interface "
1263                                 + intf.getName() + " on srcNode " + srcNode.getNodeId().getValue());
1264                         removeTunnelRules(tunnelType, segmentationId,
1265                                 dst, srcNode, intf, true, isLastInstanceOnNode);
1266                         Node dstBridgeNode = southbound.getBridgeNode(dstNode, Constants.INTEGRATION_BRIDGE);
1267                         //While removing last instance , check whether the network present in src node
1268                         //If network is not present in src node , remove the vxlan port of src from dst node in TunnelRules(Bug# 5614)
1269                         boolean isSrcinNw = tenantNetworkManager.isTenantNetworkPresentInNode(srcBridgeNode, segmentationId);
1270                         if (dstBridgeNode != null) {
1271                             if (!isSrcinNw) {
1272                                 removeTunnelRules(tunnelType, segmentationId,
1273                                     src, dstBridgeNode, intf, true, isLastInstanceOnNode);
1274                             }
1275                             LOG.info("Remove tunnel rules for interface "
1276                                     + intf.getName() + " on dstNode " + dstNode.getNodeId().getValue());
1277                             removeTunnelRules(tunnelType, segmentationId, src,
1278                                     dstBridgeNode, intf, false, isLastInstanceOnNode);
1279                         }
1280                     } else {
1281                         LOG.warn("Tunnel end-point configuration missing. Please configure it in "
1282                                         + "OpenVSwitch Table. "
1283                                         + "Check source {} or destination {}",
1284                                 src != null ? src.getHostAddress() : "null",
1285                                 dst != null ? dst.getHostAddress() : "null");
1286                     }
1287                 }
1288             }
1289         }
1290         return true;
1291     }
1292
1293     @Override
1294     public void initializeFlowRules(Node node) {
1295         initializeFlowRules(node, configurationService.getIntegrationBridgeName());
1296         initializeFlowRules(node, configurationService.getExternalBridgeName());
1297         triggerInterfaceUpdates(node);
1298     }
1299
1300     private void initializeFlowRules(Node node, String bridgeName) {
1301         Long dpid = southbound.getDataPathId(node);
1302         String datapathId = southbound.getDatapathId(node);
1303         LOG.info("initializeFlowRules: bridgeName: {}, dpid: {} - {}",
1304                 bridgeName, dpid, datapathId);
1305
1306         if (dpid == 0L) {
1307             LOG.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1308             return;
1309         }
1310
1311         /*
1312          * Table(0) Rule #1
1313          * ----------------
1314          * Match: LLDP (0x88CCL)
1315          * Action: Packet_In to Controller Reserved Port
1316          */
1317
1318         writeLLDPRule(dpid);
1319
1320         if (bridgeName.equals(configurationService.getIntegrationBridgeName()) &&
1321                 NetvirtProvidersProvider.getTableOffset() != 0) {
1322             classifierProvider.programGotoTable(dpid,true);
1323         }
1324
1325         if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1326             writeNormalRule(dpid);
1327         }
1328     }
1329
1330     /*
1331      * Create an LLDP Flow Rule to encapsulate into
1332      * a packet_in that is sent to the controller
1333      * for topology handling.
1334      * Match: Ethertype 0x88CCL
1335      * Action: Punt to Controller in a Packet_In msg
1336      */
1337
1338     private void writeLLDPRule(Long dpidLong) {
1339         classifierProvider.programLLDPPuntRule(dpidLong);
1340     }
1341
1342     /*
1343      * Create a NORMAL Table Miss Flow Rule
1344      * Match: any
1345      * Action: forward to NORMAL pipeline
1346      */
1347
1348     private void writeNormalRule(Long dpidLong) {
1349         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
1350         FlowBuilder flowBuilder = new FlowBuilder();
1351         String flowName = "NORMAL";
1352         FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable()).setPriority(0);
1353         MatchBuilder matchBuilder = new MatchBuilder();
1354         flowBuilder.setMatch(matchBuilder.build());
1355
1356         // Create the OF Actions and Instructions
1357         InstructionBuilder ib = new InstructionBuilder();
1358         InstructionsBuilder isb = new InstructionsBuilder();
1359
1360         // Instructions List Stores Individual Instructions
1361         List<Instruction> instructions = Lists.newArrayList();
1362
1363         // Call the InstructionBuilder Methods Containing Actions
1364         InstructionUtils.createNormalInstructions(FlowUtils.getNodeName(dpidLong), ib);
1365         ib.setOrder(0);
1366         ib.setKey(new InstructionKey(0));
1367         instructions.add(ib.build());
1368
1369         // Add InstructionBuilder to the Instruction(s)Builder List
1370         isb.setInstruction(instructions);
1371
1372         // Add InstructionsBuilder to FlowBuilder
1373         flowBuilder.setInstructions(isb.build());
1374         writeFlow(flowBuilder, nodeBuilder);
1375     }
1376
1377     /*
1378      * (Table:0) Ingress Tunnel Traffic
1379      * Match: OpenFlow InPort and Tunnel ID
1380      * Action: GOTO Local Table (10)
1381      * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
1382      */
1383
1384     private void handleTunnelIn(Long dpidLong, Short writeTable,
1385             Short goToTableId, String segmentationId,
1386             Long ofPort, boolean write) {
1387         classifierProvider.programTunnelIn(dpidLong, segmentationId, ofPort, write);
1388     }
1389
1390     /*
1391      * (Table:0) Ingress VLAN Traffic
1392      * Match: OpenFlow InPort and vlan ID
1393      * Action: GOTO Local Table (20)
1394      * table=0,vlan_id=0x5,in_port=10, actions=goto_table:2
1395      */
1396
1397     private void handleVlanIn(Long dpidLong, Short writeTable, Short goToTableId,
1398             String segmentationId,  Long ethPort, boolean write) {
1399         classifierProvider.programVlanIn(dpidLong, segmentationId, ethPort, write);
1400     }
1401
1402     /*
1403      * (Table:0) Egress VM Traffic Towards TEP
1404      * Match: Destination Ethernet Addr and OpenFlow InPort
1405      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1406      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1407      * actions=set_field:5->tun_id,goto_table=1"
1408      */
1409
1410     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
1411             String segmentationId, Long inPort, String attachedMac,
1412             boolean write) {
1413         classifierProvider.programLocalInPort(dpidLong, segmentationId, inPort, attachedMac, write);
1414     }
1415
1416     /*
1417      * (Table:0) Egress VM Traffic Towards TEP
1418      * Match: Source Ethernet Addr and OpenFlow InPort
1419      * Instruction: Set VLANID and GOTO Table Egress (n)
1420      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1421      * actions=push_vlan, set_field:5->vlan_id,goto_table=1"
1422      */
1423
1424     private void handleLocalInPortSetVlan(Long dpidLong, Short writeTable,
1425             Short goToTableId, String segmentationId,
1426             Long inPort, String attachedMac,
1427             boolean write) {
1428         classifierProvider.programLocalInPortSetVlan(dpidLong, segmentationId, inPort, attachedMac, write);
1429     }
1430
1431     /*
1432      * (Table:0) Drop frames source from a VM that do not
1433      * match the associated MAC address of the local VM.
1434      * Match: Low priority anything not matching the VM SMAC
1435      * Instruction: Drop
1436      * table=0,priority=16384,in_port=1 actions=drop"
1437      */
1438
1439     private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
1440         classifierProvider.programDropSrcIface(dpidLong, inPort, write);
1441     }
1442
1443     /*
1444      * (Table:1) Egress Tunnel Traffic
1445      * Match: Destination Ethernet Addr and Local InPort
1446      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1447      * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
1448      * actions=output:10,goto_table:2"
1449      */
1450     private void handleTunnelOut(Long dpidLong, Short writeTable,
1451             Short goToTableId, String segmentationId,
1452             Long OFPortOut, String attachedMac,
1453             boolean write) {
1454         l2ForwardingProvider.programTunnelOut(dpidLong, segmentationId, OFPortOut, attachedMac, write);
1455     }
1456
1457     /*
1458      * (Table:1) Egress VLAN Traffic
1459      * Match: Destination Ethernet Addr and VLAN id
1460      * Instruction: GOTO Table Table 2
1461      * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
1462      * actions= goto_table:2"
1463      */
1464     // TODO This method is referenced from commented code above (which needs to be checked)
1465     @SuppressWarnings("unused")
1466     private void handleVlanOut(Long dpidLong, Short writeTable,
1467             Short goToTableId, String segmentationId,
1468             Long ethPort, String attachedMac, boolean write) {
1469         l2ForwardingProvider.programVlanOut(dpidLong, segmentationId, ethPort, attachedMac, write);
1470     }
1471
1472     /*
1473      * (Table:1) Egress Tunnel Traffic
1474      * Match: Destination Ethernet Addr and Local InPort
1475      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1476      * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1477      * actions=output:10,output:11,goto_table:2
1478      */
1479
1480     private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
1481             Short localTable, String segmentationId,
1482             Long OFPortOut, boolean write) {
1483         l2ForwardingProvider.programTunnelFloodOut(dpidLong, segmentationId, OFPortOut, write);
1484     }
1485
1486     /*
1487      * (Table:1) Egress VLAN Traffic
1488      * Match: Destination Ethernet Addr and VLAN id
1489      * Instruction: GOTO table 2 and Output port eth interface
1490      * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1491      * actions=output:eth1,goto_table:2
1492      */
1493     // TODO This method is referenced from commented code above (which needs to be checked)
1494     @SuppressWarnings("unused")
1495     private void handleVlanFloodOut(Long dpidLong, Short writeTable,
1496             Short localTable, String segmentationId,
1497             Long localPort, Long ethPort, boolean write) {
1498         //l2ForwardingProvider.programVlanFloodOut(dpidLong, segmentationId, localPort, ethPort, write);
1499     }
1500
1501     /*
1502      * (Table:1) Table Drain w/ Catch All
1503      * Match: Tunnel ID
1504      * Action: GOTO Local Table (10)
1505      * table=2,priority=8192,tun_id=0x5 actions=drop
1506      */
1507
1508     private void handleTunnelMiss(Long dpidLong, Short writeTable,
1509             Short goToTableId, String segmentationId,
1510             boolean write) {
1511         l2ForwardingProvider.programTunnelMiss(dpidLong, segmentationId, write);
1512     }
1513
1514
1515     /*
1516      * (Table:1) Table Drain w/ Catch All
1517      * Match: Vlan ID
1518      * Action: Output port eth interface
1519      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
1520      * table=110,priority=8192,dl_vlan=2001 actions=output:2
1521      */
1522
1523     private void handleVlanMiss(Long dpidLong, Short writeTable,
1524             Short goToTableId, String segmentationId,
1525             Long ethPort, boolean write) {
1526         l2ForwardingProvider.programVlanMiss(dpidLong, segmentationId, ethPort, write);
1527     }
1528
1529     /*
1530      * (Table:1) Local Broadcast Flood
1531      * Match: Tunnel ID and dMAC
1532      * Action: Output Port
1533      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
1534      */
1535
1536     private void handleLocalUcastOut(Long dpidLong, Short writeTable,
1537             String segmentationId, Long localPort,
1538             String attachedMac, boolean write) {
1539         l2ForwardingProvider.programLocalUcastOut(dpidLong, segmentationId, localPort, attachedMac, write);
1540     }
1541
1542     /*
1543      * (Table:2) Local VLAN unicast
1544      * Match: VLAN ID and dMAC
1545      * Action: Output Port
1546      * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
1547      */
1548
1549     private void handleLocalVlanUcastOut(Long dpidLong, Short writeTable,
1550             String segmentationId, Long localPort,
1551             String attachedMac, boolean write) {
1552         l2ForwardingProvider.programLocalVlanUcastOut(dpidLong, segmentationId, localPort, attachedMac, write);
1553     }
1554
1555     /*
1556      * (Table:2) Local Broadcast Flood
1557      * Match: Tunnel ID and dMAC (::::FF:FF)
1558      * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1559      * actions=output:2,3,4,5
1560      */
1561
1562     private void handleLocalBcastOut(Long dpidLong, Short writeTable,
1563             String segmentationId, Long localPort,
1564             boolean write) {
1565         l2ForwardingProvider.programLocalBcastOut(dpidLong, segmentationId, localPort, write);
1566     }
1567
1568     /*
1569      * (Table:2) Local VLAN Broadcast Flood
1570      * Match: vlan ID and dMAC (::::FF:FF)
1571      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1572      * actions=strip_vlan, output:2,3,4,5
1573      * table=110,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
1574      */
1575
1576     private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable, String segmentationId,
1577                                          Long localPort, Long ethPort, boolean write) {
1578         l2ForwardingProvider.programLocalVlanBcastOut(dpidLong, segmentationId, localPort, ethPort, write);
1579     }
1580
1581     /*
1582      * (Table:1) Local Table Miss
1583      * Match: Any Remaining Flows w/a TunID
1584      * Action: Drop w/ a low priority
1585      * table=2,priority=8192,tun_id=0x5 actions=drop
1586      */
1587
1588     private void handleLocalTableMiss(Long dpidLong, Short writeTable,
1589             String segmentationId, boolean write) {
1590         l2ForwardingProvider.programLocalTableMiss(dpidLong, segmentationId, write);
1591     }
1592
1593     /*
1594      * (Table:1) Local Table Miss
1595      * Match: Any Remaining Flows w/a VLAN ID
1596      * Action: Drop w/ a low priority
1597      * table=2,priority=8192,vlan_id=0x5 actions=drop
1598      */
1599     // TODO This method is referenced from commented code above (which needs to be checked)
1600     @SuppressWarnings("unused")
1601     private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
1602             String segmentationId, boolean write) {
1603         l2ForwardingProvider.programLocalVlanTableMiss(dpidLong, segmentationId, write);
1604     }
1605
1606     private Group getGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
1607         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1608                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
1609                         new GroupKey(groupBuilder.getGroupId())).build();
1610         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
1611         try {
1612             Optional<Group> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
1613             if (data.isPresent()) {
1614                 return data.get();
1615             }
1616         } catch (InterruptedException|ExecutionException e) {
1617             LOG.error("Failed to get group {}", groupBuilder.getGroupName(), e);
1618         }
1619
1620         LOG.debug("Cannot find data for Group {}", groupBuilder.getGroupName());
1621         return null;
1622     }
1623
1624     private void writeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
1625         if (NetvirtProvidersProvider.isMasterProviderInstance()) {
1626             ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
1627             InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1628                     .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
1629                             new GroupKey(groupBuilder.getGroupId())).build();
1630             modification.put(LogicalDatastoreType.CONFIGURATION, path1, groupBuilder.build(), true /*createMissingParents*/);
1631
1632             CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
1633             try {
1634                 commitFuture.get();  // TODO: Make it async (See bug 1362)
1635                 LOG.debug("Transaction success for write of Group {}", groupBuilder.getGroupName());
1636             } catch (InterruptedException|ExecutionException e) {
1637                 LOG.error("Failed to write group {}", groupBuilder.getGroupName(), e);
1638             }
1639         }
1640     }
1641
1642     private void removeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
1643         if (NetvirtProvidersProvider.isMasterProviderInstance()) {
1644             WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
1645             InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1646                     .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
1647                             new GroupKey(groupBuilder.getGroupId())).build();
1648             modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
1649             CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
1650
1651             try {
1652                 commitFuture.get();  // TODO: Make it async (See bug 1362)
1653                 LOG.debug("Transaction success for deletion of Group {}", groupBuilder.getGroupName());
1654             } catch (InterruptedException|ExecutionException e) {
1655                 LOG.error("Failed to remove group {}", groupBuilder.getGroupName(), e);
1656             }
1657         }
1658     }
1659
1660     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
1661         if (NetvirtProvidersProvider.isMasterProviderInstance()){
1662             ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
1663             InstanceIdentifier<Flow> path1 =
1664                     InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1665                                     .rev130819.nodes.Node.class,
1666                             nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
1667                             new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
1668
1669             //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
1670             modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(),
1671                     true);//createMissingParents
1672
1673
1674             CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
1675             try {
1676                 commitFuture.get();  // TODO: Make it async (See bug 1362)
1677                 LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
1678             } catch (InterruptedException|ExecutionException e) {
1679                 LOG.error("Failed to write flows {}", flowBuilder.getFlowName(), e);
1680             }
1681         }
1682     }
1683
1684     /**
1685      * Create Output Port Group Instruction
1686      *
1687      * @param ib       Map InstructionBuilder without any instructions
1688      * @param dpidLong Long the datapath ID of a switch/node
1689      * @param port     Long representing a port on a switch/node
1690      * @return ib InstructionBuilder Map with instructions
1691      */
1692     // TODO This method is referenced from commented code in L2ForwardingService (which needs to be checked)
1693     @SuppressWarnings("unused")
1694     protected InstructionBuilder createOutputGroupInstructions(NodeBuilder nodeBuilder,
1695             InstructionBuilder ib,
1696             Long dpidLong, Long port ,
1697             List<Instruction> instructions) {
1698         NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
1699         LOG.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1700
1701         List<Action> actionList = Lists.newArrayList();
1702         ActionBuilder ab = new ActionBuilder();
1703
1704         List<Action> existingActions;
1705         if (instructions != null) {
1706             for (Instruction in : instructions) {
1707                 if (in.getInstruction() instanceof ApplyActionsCase) {
1708                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1709                     actionList.addAll(existingActions);
1710                 }
1711             }
1712         }
1713
1714         GroupBuilder groupBuilder = new GroupBuilder();
1715         Group group = null;
1716
1717         /* Create output action for this port*/
1718         OutputActionBuilder oab = new OutputActionBuilder();
1719         oab.setOutputNodeConnector(ncid);
1720         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
1721         LOG.debug("createOutputGroupInstructions(): output action {}", ab.build());
1722         boolean addNew = true;
1723         boolean groupActionAdded = false;
1724
1725         /* Find the group action and get the group */
1726         for (Action action : actionList) {
1727             if (action.getAction() instanceof GroupActionCase) {
1728                 groupActionAdded = true;
1729                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
1730                 Long id = groupAction.getGroupAction().getGroupId();
1731                 String groupName = groupAction.getGroupAction().getGroup();
1732                 GroupKey key = new GroupKey(new GroupId(id));
1733
1734                 groupBuilder.setGroupId(new GroupId(id));
1735                 groupBuilder.setGroupName(groupName);
1736                 groupBuilder.setGroupType(GroupTypes.GroupAll);
1737                 groupBuilder.setKey(key);
1738                 group = getGroup(groupBuilder, nodeBuilder);
1739                 LOG.debug("createOutputGroupInstructions: group {}", group);
1740                 break;
1741             }
1742         }
1743
1744         LOG.debug("createOutputGroupInstructions: groupActionAdded {}", groupActionAdded);
1745         if (groupActionAdded) {
1746             /* modify the action bucket in group */
1747             groupBuilder = new GroupBuilder(group);
1748             Buckets buckets = groupBuilder.getBuckets();
1749             for (Bucket bucket : buckets.getBucket()) {
1750                 List<Action> bucketActions = bucket.getAction();
1751                 LOG.debug("createOutputGroupInstructions: bucketActions {}", bucketActions);
1752                 for (Action action : bucketActions) {
1753                     if (action.getAction() instanceof OutputActionCase) {
1754                         OutputActionCase opAction = (OutputActionCase)action.getAction();
1755                         /* If output port action already in the action list of one of the buckets, skip */
1756                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1757                             addNew = false;
1758                             break;
1759                         }
1760                     }
1761                 }
1762             }
1763             LOG.debug("createOutputGroupInstructions: addNew {}", addNew);
1764             if (addNew && !buckets.getBucket().isEmpty()) {
1765                 /* the new output action is not in the bucket, add to bucket */
1766                 Bucket bucket = buckets.getBucket().get(0);
1767                 List<Action> bucketActionList = Lists.newArrayList();
1768                 bucketActionList.addAll(bucket.getAction());
1769                 /* set order for new action and add to action list */
1770                 ab.setOrder(bucketActionList.size());
1771                 ab.setKey(new ActionKey(bucketActionList.size()));
1772                 bucketActionList.add(ab.build());
1773
1774                 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
1775                 BucketsBuilder bucketsBuilder = new BucketsBuilder();
1776                 List<Bucket> bucketList = Lists.newArrayList();
1777                 BucketBuilder bucketBuilder = new BucketBuilder();
1778                 bucketBuilder.setBucketId(new BucketId((long) 1));
1779                 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
1780                 bucketBuilder.setAction(bucketActionList);
1781                 bucketList.add(bucketBuilder.build());
1782                 bucketsBuilder.setBucket(bucketList);
1783                 groupBuilder.setBuckets(bucketsBuilder.build());
1784                 LOG.debug("createOutputGroupInstructions: bucketList {}", bucketList);
1785             }
1786         } else {
1787             /* create group */
1788             groupBuilder = new GroupBuilder();
1789             groupBuilder.setGroupType(GroupTypes.GroupAll);
1790             groupBuilder.setGroupId(new GroupId(groupId));
1791             groupBuilder.setKey(new GroupKey(new GroupId(groupId)));
1792             groupBuilder.setGroupName("Output port group " + groupId);
1793             groupBuilder.setBarrier(false);
1794
1795             BucketsBuilder bucketBuilder = new BucketsBuilder();
1796             List<Bucket> bucketList = Lists.newArrayList();
1797             BucketBuilder bucket = new BucketBuilder();
1798             bucket.setBucketId(new BucketId((long) 1));
1799             bucket.setKey(new BucketKey(new BucketId((long) 1)));
1800
1801             /* put output action to the bucket */
1802             List<Action> bucketActionList = Lists.newArrayList();
1803             /* set order for new action and add to action list */
1804             ab.setOrder(bucketActionList.size());
1805             ab.setKey(new ActionKey(bucketActionList.size()));
1806             bucketActionList.add(ab.build());
1807
1808             bucket.setAction(bucketActionList);
1809             bucketList.add(bucket.build());
1810             bucketBuilder.setBucket(bucketList);
1811             groupBuilder.setBuckets(bucketBuilder.build());
1812
1813             /* Add new group action */
1814             GroupActionBuilder groupActionB = new GroupActionBuilder();
1815             groupActionB.setGroupId(groupId);
1816             groupActionB.setGroup("Output port group " + groupId);
1817             ab = new ActionBuilder();
1818             ab.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionB.build()).build());
1819             ab.setOrder(actionList.size());
1820             ab.setKey(new ActionKey(actionList.size()));
1821             actionList.add(ab.build());
1822
1823             groupId++;
1824         }
1825         LOG.debug("createOutputGroupInstructions: group {}", groupBuilder.build());
1826         LOG.debug("createOutputGroupInstructions: actionList {}", actionList);
1827
1828         if (addNew) {
1829             /* rewrite the group to group table */
1830             writeGroup(groupBuilder, nodeBuilder);
1831         }
1832
1833         // Create an Apply Action
1834         ApplyActionsBuilder aab = new ApplyActionsBuilder();
1835         aab.setAction(actionList);
1836         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1837
1838         return ib;
1839     }
1840
1841     /**
1842      * Remove Output Port from action list in group bucket
1843      *
1844      * @param ib       Map InstructionBuilder without any instructions
1845      * @param dpidLong Long the datapath ID of a switch/node
1846      * @param port     Long representing a port on a switch/node
1847      * @return ib InstructionBuilder Map with instructions
1848      */
1849     // TODO This method is referenced from commented code in L2ForwardingService (which needs to be checked)
1850     @SuppressWarnings("unused")
1851     protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
1852             Long dpidLong, Long port , List<Instruction> instructions) {
1853
1854         NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
1855         LOG.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1856
1857         List<Action> actionList = Lists.newArrayList();
1858         ActionBuilder ab;
1859
1860         List<Action> existingActions;
1861         if (instructions != null) {
1862             for (Instruction in : instructions) {
1863                 if (in.getInstruction() instanceof ApplyActionsCase) {
1864                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1865                     actionList.addAll(existingActions);
1866                     break;
1867                 }
1868             }
1869         }
1870
1871         GroupBuilder groupBuilder = new GroupBuilder();
1872         Group group = null;
1873         boolean groupActionAdded = false;
1874         /* Find the group action and get the group */
1875         for (Action action : actionList) {
1876             if (action.getAction() instanceof GroupActionCase) {
1877                 groupActionAdded = true;
1878                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
1879                 Long id = groupAction.getGroupAction().getGroupId();
1880                 String groupName = groupAction.getGroupAction().getGroup();
1881                 GroupKey key = new GroupKey(new GroupId(id));
1882
1883                 groupBuilder.setGroupId(new GroupId(id));
1884                 groupBuilder.setGroupName(groupName);
1885                 groupBuilder.setGroupType(GroupTypes.GroupAll);
1886                 groupBuilder.setKey(key);
1887                 group = getGroup(groupBuilder, nodeBuilder);
1888                 break;
1889             }
1890         }
1891
1892         if (groupActionAdded) {
1893             /* modify the action bucket in group */
1894             groupBuilder = new GroupBuilder(group);
1895             Buckets buckets = groupBuilder.getBuckets();
1896             List<Action> bucketActions = Lists.newArrayList();
1897             for (Bucket bucket : buckets.getBucket()) {
1898                 int index = 0;
1899                 boolean isPortDeleted = false;
1900                 bucketActions = bucket.getAction();
1901                 for (Action action : bucketActions) {
1902                     if (action.getAction() instanceof OutputActionCase) {
1903                         OutputActionCase opAction = (OutputActionCase)action.getAction();
1904                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1905                             /* Find the output port in action list and remove */
1906                             index = bucketActions.indexOf(action);
1907                             bucketActions.remove(action);
1908                             isPortDeleted = true;
1909                             break;
1910                         }
1911                     }
1912                 }
1913                 if (isPortDeleted && !bucketActions.isEmpty()) {
1914                     for (int i = index; i< bucketActions.size(); i++) {
1915                         Action action = bucketActions.get(i);
1916                         if (action.getOrder() != i) {
1917                             /* Shift the action order */
1918                             ab = new ActionBuilder();
1919                             ab.setAction(action.getAction());
1920                             ab.setOrder(i);
1921                             ab.setKey(new ActionKey(i));
1922                             Action actionNewOrder = ab.build();
1923                             bucketActions.remove(action);
1924                             bucketActions.add(i, actionNewOrder);
1925                         }
1926                     }
1927
1928                 } else if (bucketActions.isEmpty()) {
1929                     /* remove bucket with empty action list */
1930                     buckets.getBucket().remove(bucket);
1931                     break;
1932                 }
1933             }
1934             if (!buckets.getBucket().isEmpty()) {
1935                 /* rewrite the group to group table */
1936                 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
1937                 BucketsBuilder bucketsBuilder = new BucketsBuilder();
1938                 List<Bucket> bucketList = Lists.newArrayList();
1939                 BucketBuilder bucketBuilder = new BucketBuilder();
1940                 bucketBuilder.setBucketId(new BucketId((long) 1));
1941                 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
1942                 bucketBuilder.setAction(bucketActions);
1943                 bucketList.add(bucketBuilder.build());
1944                 bucketsBuilder.setBucket(bucketList);
1945                 groupBuilder.setBuckets(bucketsBuilder.build());
1946                 LOG.debug("removeOutputPortFromGroup: bucketList {}", bucketList);
1947
1948                 writeGroup(groupBuilder, nodeBuilder);
1949                 ApplyActionsBuilder aab = new ApplyActionsBuilder();
1950                 aab.setAction(actionList);
1951                 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1952                 return false;
1953             } else {
1954                 /* remove group with empty bucket. return true to delete flow */
1955                 removeGroup(groupBuilder, nodeBuilder);
1956                 return true;
1957             }
1958         } else {
1959             /* no group for port list. flow can be removed */
1960             return true;
1961         }
1962     }
1963
1964     @Override
1965     public void initializeOFFlowRules(Node openflowNode) {
1966         String bridgeName = southbound.getBridgeName(openflowNode);
1967         LOG.info("initializeOFFlowRules: bridgeName: {}", bridgeName);
1968         if (bridgeName.equals(configurationService.getIntegrationBridgeName())) {
1969             initializeFlowRules(openflowNode, configurationService.getIntegrationBridgeName());
1970             triggerInterfaceUpdates(openflowNode);
1971         } else if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1972             initializeFlowRules(openflowNode, configurationService.getExternalBridgeName());
1973             LOG.info("initializeOFFlowRules after writeFlow: bridgeName: {}", bridgeName);
1974             triggerInterfaceUpdates(openflowNode);
1975             LOG.info("initializeOFFlowRules after triggerUpdates: bridgeName: {}", bridgeName);
1976         }
1977     }
1978
1979     public static NodeBuilder createNodeBuilder(String nodeId) {
1980         NodeBuilder builder = new NodeBuilder();
1981         builder.setId(new NodeId(nodeId));
1982         builder.setKey(new NodeKey(builder.getId()));
1983         return builder;
1984     }
1985
1986     @Override
1987     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1988         this.bundleContext = bundleContext;
1989         configurationService =
1990                 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
1991         tenantNetworkManager =
1992                 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
1993         bridgeConfigurationManager =
1994                 (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this);
1995         nodeCacheManager =
1996                 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
1997         classifierProvider =
1998                 (ClassifierProvider) ServiceHelper.getGlobalInstance(ClassifierProvider.class, this);
1999         ingressAclProvider =
2000                 (IngressAclProvider) ServiceHelper.getGlobalInstance(IngressAclProvider.class, this);
2001         egressAclProvider =
2002                 (EgressAclProvider) ServiceHelper.getGlobalInstance(EgressAclProvider.class, this);
2003         l2ForwardingProvider =
2004                 (L2ForwardingProvider) ServiceHelper.getGlobalInstance(L2ForwardingProvider.class, this);
2005         securityServicesManager =
2006                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
2007         southbound =
2008                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
2009     }
2010
2011     @Override
2012     public void setDependencies(Object impl) {
2013         if (impl instanceof NetworkingProviderManager) {
2014             NetworkingProviderManager networkingProviderManager = (NetworkingProviderManager) impl;
2015             networkingProviderManager.providerAdded(
2016                     bundleContext.getServiceReference(NetworkingProvider.class.getName()), this);
2017         }
2018     }
2019 }