Bug 6066 - Improve the logging.
[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.rev130715.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("Added TunnelPort : 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                     if (sourceTunnelStatus &&  destTunnelStatus) {
1172                         LOG.debug("Created Source and destination TunnelPorts :{}, {}", src, dst);
1173                     }  else {
1174                         LOG.debug("Source and destination TunnelPort status :{}, {}", sourceTunnelStatus, destTunnelStatus);
1175                     }
1176                     if (sourceTunnelStatus) {
1177                         boolean isDestinNw = tenantNetworkManager.isTenantNetworkPresentInNode(dstBridgeNode, segmentationId);
1178                         //Check whether the network is present in src & dst node
1179                         //If only present , add vxlan ports in TunnelRules for both nodes (bug# 5614)
1180                         if (isSrcinNw && isDestinNw) {
1181                             programTunnelRules(networkType, segmentationId, dst, srcBridgeNode, intf, true);
1182                             programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, true);
1183                         }
1184                     }
1185                     if (destTunnelStatus) {
1186                         programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, false);
1187
1188                         if (srcNodeId != null && intBridgesWithoutVmPorts.contains(srcNodeId)) {
1189                             programTunnelRulesInNewNode(network, networkType, segmentationId, src, dst,
1190                                     srcBridgeNode, dstBridgeNode, intf);
1191                             intBridgesWithoutVmPorts.remove(srcNodeId);
1192                         }
1193                     }
1194                 } else {
1195                     LOG.warn("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table. "
1196                                     + "Check source {} or destination {}",
1197                             src != null ? src.getHostAddress() : "null",
1198                             dst != null ? dst.getHostAddress() : "null");
1199                 }
1200             }
1201         }
1202
1203         if (srcNodeId != null && !bridgeHasVmPort(srcNode)) {
1204             intBridgesWithoutVmPorts.add(srcNodeId);
1205         }
1206
1207         return true;
1208     }
1209
1210     private void triggerInterfaceUpdates(Node node) {
1211         LOG.debug("enter triggerInterfaceUpdates for : {}", node.getNodeId());
1212         List<OvsdbTerminationPointAugmentation> ports = southbound.extractTerminationPointAugmentations(node);
1213         if (ports != null && !ports.isEmpty()) {
1214             for (OvsdbTerminationPointAugmentation port : ports) {
1215                 NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(port);
1216                 if (neutronNetwork != null) {
1217                     LOG.warn("Trigger Interface update for {}", port);
1218                     handleInterfaceUpdate(neutronNetwork, node, port);
1219                 }
1220             }
1221         } else {
1222             LOG.warn("triggerInterfaceUpdates: tps are null");
1223         }
1224         LOG.debug("exit triggerInterfaceUpdates for {}", node.getNodeId());
1225     }
1226
1227     @Override
1228     public boolean handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode,
1229                                          OvsdbTerminationPointAugmentation intf, boolean isLastInstanceOnNode) {
1230         Map<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId,Node> nodes =
1231                 nodeCacheManager.getOvsdbNodes();
1232         nodes.remove(southbound.extractBridgeOvsdbNodeId(srcNode));
1233
1234         LOG.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
1235         String segmentationId = network.getProviderSegmentationID();
1236         List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(srcNode);
1237         if (southbound.isTunnel(intf)) {
1238             // Delete tunnel port
1239             try {
1240                 InetAddress src = InetAddress.getByName(
1241                         southbound.getOptionsValue(intf.getOptions(), "local_ip"));
1242                 InetAddress dst = InetAddress.getByName(
1243                         southbound.getOptionsValue(intf.getOptions(), "remote_ip"));
1244                 deleteTunnelPort(srcNode,
1245                         MdsalHelper.createOvsdbInterfaceType(intf.getInterfaceType()),
1246                         src, dst);
1247             } catch (Exception e) {
1248                 LOG.error("handleInterfaceDelete: failed to delete tunnel port", e);
1249             }
1250         } else if (phyIfName.contains(intf.getName())) {
1251             deletePhysicalPort(srcNode, intf.getName());
1252         } else {
1253             // delete all other interfaces
1254             removeLocalRules(network.getProviderNetworkType(), segmentationId,
1255                     srcNode, intf);
1256
1257             if (isVlan(network.getProviderNetworkType())) {
1258                 removeVlanRules(network, srcNode, intf, isLastInstanceOnNode);
1259             } else if (isTunnel(network.getProviderNetworkType())) {
1260
1261                 Node srcBridgeNode = southbound.getBridgeNode(srcNode, configurationService.getIntegrationBridgeName());
1262                 for (Node dstNode : nodes.values()) {
1263                     InetAddress src = configurationService.getTunnelEndPoint(srcNode);
1264                     InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
1265                     if ((src != null) && (dst != null)) {
1266                         LOG.info("Remove tunnel rules for interface "
1267                                 + intf.getName() + " on srcNode " + srcNode.getNodeId().getValue());
1268                         removeTunnelRules(tunnelType, segmentationId,
1269                                 dst, srcNode, intf, true, isLastInstanceOnNode);
1270                         Node dstBridgeNode = southbound.getBridgeNode(dstNode, Constants.INTEGRATION_BRIDGE);
1271                         //While removing last instance , check whether the network present in src node
1272                         //If network is not present in src node , remove the vxlan port of src from dst node in TunnelRules(Bug# 5614)
1273                         boolean isSrcinNw = tenantNetworkManager.isTenantNetworkPresentInNode(srcBridgeNode, segmentationId);
1274                         if (dstBridgeNode != null) {
1275                             if (!isSrcinNw) {
1276                                 removeTunnelRules(tunnelType, segmentationId,
1277                                     src, dstBridgeNode, intf, true, isLastInstanceOnNode);
1278                             }
1279                             LOG.info("Remove tunnel rules for interface "
1280                                     + intf.getName() + " on dstNode " + dstNode.getNodeId().getValue());
1281                             removeTunnelRules(tunnelType, segmentationId, src,
1282                                     dstBridgeNode, intf, false, isLastInstanceOnNode);
1283                         }
1284                     } else {
1285                         LOG.warn("Tunnel end-point configuration missing. Please configure it in "
1286                                         + "OpenVSwitch Table. "
1287                                         + "Check source {} or destination {}",
1288                                 src != null ? src.getHostAddress() : "null",
1289                                 dst != null ? dst.getHostAddress() : "null");
1290                     }
1291                 }
1292             }
1293         }
1294         return true;
1295     }
1296
1297     @Override
1298     public void initializeFlowRules(Node node) {
1299         initializeFlowRules(node, configurationService.getIntegrationBridgeName());
1300         initializeFlowRules(node, configurationService.getExternalBridgeName());
1301         triggerInterfaceUpdates(node);
1302     }
1303
1304     private void initializeFlowRules(Node node, String bridgeName) {
1305         Long dpid = southbound.getDataPathId(node);
1306         String datapathId = southbound.getDatapathId(node);
1307         LOG.trace("initializeFlowRules: bridgeName: {}, datapathId: {} ",
1308                 bridgeName, datapathId);
1309
1310         if (dpid == 0L) {
1311             LOG.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
1312             return;
1313         }
1314
1315         /*
1316          * Table(0) Rule #1
1317          * ----------------
1318          * Match: LLDP (0x88CCL)
1319          * Action: Packet_In to Controller Reserved Port
1320          */
1321
1322         writeLLDPRule(dpid);
1323
1324         if (bridgeName.equals(configurationService.getIntegrationBridgeName()) &&
1325                 NetvirtProvidersProvider.getTableOffset() != 0) {
1326             classifierProvider.programGotoTable(dpid,true);
1327         }
1328
1329         if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1330             writeNormalRule(dpid);
1331         }
1332     }
1333
1334     /*
1335      * Create an LLDP Flow Rule to encapsulate into
1336      * a packet_in that is sent to the controller
1337      * for topology handling.
1338      * Match: Ethertype 0x88CCL
1339      * Action: Punt to Controller in a Packet_In msg
1340      */
1341
1342     private void writeLLDPRule(Long dpidLong) {
1343         classifierProvider.programLLDPPuntRule(dpidLong);
1344     }
1345
1346     /*
1347      * Create a NORMAL Table Miss Flow Rule
1348      * Match: any
1349      * Action: forward to NORMAL pipeline
1350      */
1351
1352     private void writeNormalRule(Long dpidLong) {
1353         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
1354         FlowBuilder flowBuilder = new FlowBuilder();
1355         String flowName = "NORMAL";
1356         FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable()).setPriority(0);
1357         MatchBuilder matchBuilder = new MatchBuilder();
1358         flowBuilder.setMatch(matchBuilder.build());
1359
1360         // Create the OF Actions and Instructions
1361         InstructionBuilder ib = new InstructionBuilder();
1362         InstructionsBuilder isb = new InstructionsBuilder();
1363
1364         // Instructions List Stores Individual Instructions
1365         List<Instruction> instructions = Lists.newArrayList();
1366
1367         // Call the InstructionBuilder Methods Containing Actions
1368         InstructionUtils.createNormalInstructions(FlowUtils.getNodeName(dpidLong), ib);
1369         ib.setOrder(0);
1370         ib.setKey(new InstructionKey(0));
1371         instructions.add(ib.build());
1372
1373         // Add InstructionBuilder to the Instruction(s)Builder List
1374         isb.setInstruction(instructions);
1375
1376         // Add InstructionsBuilder to FlowBuilder
1377         flowBuilder.setInstructions(isb.build());
1378         writeFlow(flowBuilder, nodeBuilder);
1379     }
1380
1381     /*
1382      * (Table:0) Ingress Tunnel Traffic
1383      * Match: OpenFlow InPort and Tunnel ID
1384      * Action: GOTO Local Table (10)
1385      * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
1386      */
1387
1388     private void handleTunnelIn(Long dpidLong, Short writeTable,
1389             Short goToTableId, String segmentationId,
1390             Long ofPort, boolean write) {
1391         classifierProvider.programTunnelIn(dpidLong, segmentationId, ofPort, write);
1392     }
1393
1394     /*
1395      * (Table:0) Ingress VLAN Traffic
1396      * Match: OpenFlow InPort and vlan ID
1397      * Action: GOTO Local Table (20)
1398      * table=0,vlan_id=0x5,in_port=10, actions=goto_table:2
1399      */
1400
1401     private void handleVlanIn(Long dpidLong, Short writeTable, Short goToTableId,
1402             String segmentationId,  Long ethPort, boolean write) {
1403         classifierProvider.programVlanIn(dpidLong, segmentationId, ethPort, write);
1404     }
1405
1406     /*
1407      * (Table:0) Egress VM Traffic Towards TEP
1408      * Match: Destination Ethernet Addr and OpenFlow InPort
1409      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1410      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1411      * actions=set_field:5->tun_id,goto_table=1"
1412      */
1413
1414     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
1415             String segmentationId, Long inPort, String attachedMac,
1416             boolean write) {
1417         classifierProvider.programLocalInPort(dpidLong, segmentationId, inPort, attachedMac, write);
1418     }
1419
1420     /*
1421      * (Table:0) Egress VM Traffic Towards TEP
1422      * Match: Source Ethernet Addr and OpenFlow InPort
1423      * Instruction: Set VLANID and GOTO Table Egress (n)
1424      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
1425      * actions=push_vlan, set_field:5->vlan_id,goto_table=1"
1426      */
1427
1428     private void handleLocalInPortSetVlan(Long dpidLong, Short writeTable,
1429             Short goToTableId, String segmentationId,
1430             Long inPort, String attachedMac,
1431             boolean write) {
1432         classifierProvider.programLocalInPortSetVlan(dpidLong, segmentationId, inPort, attachedMac, write);
1433     }
1434
1435     /*
1436      * (Table:0) Drop frames source from a VM that do not
1437      * match the associated MAC address of the local VM.
1438      * Match: Low priority anything not matching the VM SMAC
1439      * Instruction: Drop
1440      * table=0,priority=16384,in_port=1 actions=drop"
1441      */
1442
1443     private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
1444         classifierProvider.programDropSrcIface(dpidLong, inPort, write);
1445     }
1446
1447     /*
1448      * (Table:1) Egress Tunnel Traffic
1449      * Match: Destination Ethernet Addr and Local InPort
1450      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1451      * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
1452      * actions=output:10,goto_table:2"
1453      */
1454     private void handleTunnelOut(Long dpidLong, Short writeTable,
1455             Short goToTableId, String segmentationId,
1456             Long OFPortOut, String attachedMac,
1457             boolean write) {
1458         l2ForwardingProvider.programTunnelOut(dpidLong, segmentationId, OFPortOut, attachedMac, write);
1459     }
1460
1461     /*
1462      * (Table:1) Egress VLAN Traffic
1463      * Match: Destination Ethernet Addr and VLAN id
1464      * Instruction: GOTO Table Table 2
1465      * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
1466      * actions= goto_table:2"
1467      */
1468     // TODO This method is referenced from commented code above (which needs to be checked)
1469     @SuppressWarnings("unused")
1470     private void handleVlanOut(Long dpidLong, Short writeTable,
1471             Short goToTableId, String segmentationId,
1472             Long ethPort, String attachedMac, boolean write) {
1473         l2ForwardingProvider.programVlanOut(dpidLong, segmentationId, ethPort, attachedMac, write);
1474     }
1475
1476     /*
1477      * (Table:1) Egress Tunnel Traffic
1478      * Match: Destination Ethernet Addr and Local InPort
1479      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
1480      * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1481      * actions=output:10,output:11,goto_table:2
1482      */
1483
1484     private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
1485             Short localTable, String segmentationId,
1486             Long OFPortOut, boolean write) {
1487         l2ForwardingProvider.programTunnelFloodOut(dpidLong, segmentationId, OFPortOut, write);
1488     }
1489
1490     /*
1491      * (Table:1) Egress VLAN Traffic
1492      * Match: Destination Ethernet Addr and VLAN id
1493      * Instruction: GOTO table 2 and Output port eth interface
1494      * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1495      * actions=output:eth1,goto_table:2
1496      */
1497     // TODO This method is referenced from commented code above (which needs to be checked)
1498     @SuppressWarnings("unused")
1499     private void handleVlanFloodOut(Long dpidLong, Short writeTable,
1500             Short localTable, String segmentationId,
1501             Long localPort, Long ethPort, boolean write) {
1502         //l2ForwardingProvider.programVlanFloodOut(dpidLong, segmentationId, localPort, ethPort, write);
1503     }
1504
1505     /*
1506      * (Table:1) Table Drain w/ Catch All
1507      * Match: Tunnel ID
1508      * Action: GOTO Local Table (10)
1509      * table=2,priority=8192,tun_id=0x5 actions=drop
1510      */
1511
1512     private void handleTunnelMiss(Long dpidLong, Short writeTable,
1513             Short goToTableId, String segmentationId,
1514             boolean write) {
1515         l2ForwardingProvider.programTunnelMiss(dpidLong, segmentationId, write);
1516     }
1517
1518
1519     /*
1520      * (Table:1) Table Drain w/ Catch All
1521      * Match: Vlan ID
1522      * Action: Output port eth interface
1523      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
1524      * table=110,priority=8192,dl_vlan=2001 actions=output:2
1525      */
1526
1527     private void handleVlanMiss(Long dpidLong, Short writeTable,
1528             Short goToTableId, String segmentationId,
1529             Long ethPort, boolean write) {
1530         l2ForwardingProvider.programVlanMiss(dpidLong, segmentationId, ethPort, write);
1531     }
1532
1533     /*
1534      * (Table:1) Local Broadcast Flood
1535      * Match: Tunnel ID and dMAC
1536      * Action: Output Port
1537      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
1538      */
1539
1540     private void handleLocalUcastOut(Long dpidLong, Short writeTable,
1541             String segmentationId, Long localPort,
1542             String attachedMac, boolean write) {
1543         l2ForwardingProvider.programLocalUcastOut(dpidLong, segmentationId, localPort, attachedMac, write);
1544     }
1545
1546     /*
1547      * (Table:2) Local VLAN unicast
1548      * Match: VLAN ID and dMAC
1549      * Action: Output Port
1550      * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
1551      */
1552
1553     private void handleLocalVlanUcastOut(Long dpidLong, Short writeTable,
1554             String segmentationId, Long localPort,
1555             String attachedMac, boolean write) {
1556         l2ForwardingProvider.programLocalVlanUcastOut(dpidLong, segmentationId, localPort, attachedMac, write);
1557     }
1558
1559     /*
1560      * (Table:2) Local Broadcast Flood
1561      * Match: Tunnel ID and dMAC (::::FF:FF)
1562      * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1563      * actions=output:2,3,4,5
1564      */
1565
1566     private void handleLocalBcastOut(Long dpidLong, Short writeTable,
1567             String segmentationId, Long localPort,
1568             boolean write) {
1569         l2ForwardingProvider.programLocalBcastOut(dpidLong, segmentationId, localPort, write);
1570     }
1571
1572     /*
1573      * (Table:2) Local VLAN Broadcast Flood
1574      * Match: vlan ID and dMAC (::::FF:FF)
1575      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
1576      * actions=strip_vlan, output:2,3,4,5
1577      * 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
1578      */
1579
1580     private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable, String segmentationId,
1581                                          Long localPort, Long ethPort, boolean write) {
1582         l2ForwardingProvider.programLocalVlanBcastOut(dpidLong, segmentationId, localPort, ethPort, write);
1583     }
1584
1585     /*
1586      * (Table:1) Local Table Miss
1587      * Match: Any Remaining Flows w/a TunID
1588      * Action: Drop w/ a low priority
1589      * table=2,priority=8192,tun_id=0x5 actions=drop
1590      */
1591
1592     private void handleLocalTableMiss(Long dpidLong, Short writeTable,
1593             String segmentationId, boolean write) {
1594         l2ForwardingProvider.programLocalTableMiss(dpidLong, segmentationId, write);
1595     }
1596
1597     /*
1598      * (Table:1) Local Table Miss
1599      * Match: Any Remaining Flows w/a VLAN ID
1600      * Action: Drop w/ a low priority
1601      * table=2,priority=8192,vlan_id=0x5 actions=drop
1602      */
1603     // TODO This method is referenced from commented code above (which needs to be checked)
1604     @SuppressWarnings("unused")
1605     private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
1606             String segmentationId, boolean write) {
1607         l2ForwardingProvider.programLocalVlanTableMiss(dpidLong, segmentationId, write);
1608     }
1609
1610     private Group getGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
1611         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1612                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
1613                         new GroupKey(groupBuilder.getGroupId())).build();
1614         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
1615         try {
1616             Optional<Group> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
1617             if (data.isPresent()) {
1618                 return data.get();
1619             }
1620         } catch (InterruptedException|ExecutionException e) {
1621             LOG.error("Failed to get group {}", groupBuilder.getGroupName(), e);
1622         }
1623
1624         LOG.debug("Cannot find data for Group {}", groupBuilder.getGroupName());
1625         return null;
1626     }
1627
1628     private void writeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
1629         if (NetvirtProvidersProvider.isMasterProviderInstance()) {
1630             ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
1631             InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1632                     .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
1633                             new GroupKey(groupBuilder.getGroupId())).build();
1634             modification.put(LogicalDatastoreType.CONFIGURATION, path1, groupBuilder.build(), true /*createMissingParents*/);
1635
1636             CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
1637             try {
1638                 commitFuture.get();  // TODO: Make it async (See bug 1362)
1639                 LOG.debug("Transaction success for write of Group {}", groupBuilder.getGroupName());
1640             } catch (InterruptedException|ExecutionException e) {
1641                 LOG.error("Failed to write group {}", groupBuilder.getGroupName(), e);
1642             }
1643         }
1644     }
1645
1646     private void removeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
1647         if (NetvirtProvidersProvider.isMasterProviderInstance()) {
1648             WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
1649             InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1650                     .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
1651                             new GroupKey(groupBuilder.getGroupId())).build();
1652             modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
1653             CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
1654
1655             try {
1656                 commitFuture.get();  // TODO: Make it async (See bug 1362)
1657                 LOG.debug("Transaction success for deletion of Group {}", groupBuilder.getGroupName());
1658             } catch (InterruptedException|ExecutionException e) {
1659                 LOG.error("Failed to remove group {}", groupBuilder.getGroupName(), e);
1660             }
1661         }
1662     }
1663
1664     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
1665         if (NetvirtProvidersProvider.isMasterProviderInstance()){
1666             ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
1667             InstanceIdentifier<Flow> path1 =
1668                     InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
1669                                     .rev130819.nodes.Node.class,
1670                             nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
1671                             new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
1672
1673             //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
1674             modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(),
1675                     true);//createMissingParents
1676
1677
1678             CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
1679             try {
1680                 commitFuture.get();  // TODO: Make it async (See bug 1362)
1681                 LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
1682             } catch (InterruptedException|ExecutionException e) {
1683                 LOG.error("Failed to write flows {}", flowBuilder.getFlowName(), e);
1684             }
1685         }
1686     }
1687
1688     /**
1689      * Create Output Port Group Instruction
1690      *
1691      * @param ib       Map InstructionBuilder without any instructions
1692      * @param dpidLong Long the datapath ID of a switch/node
1693      * @param port     Long representing a port on a switch/node
1694      * @return ib InstructionBuilder Map with instructions
1695      */
1696     // TODO This method is referenced from commented code in L2ForwardingService (which needs to be checked)
1697     @SuppressWarnings("unused")
1698     protected InstructionBuilder createOutputGroupInstructions(NodeBuilder nodeBuilder,
1699             InstructionBuilder ib,
1700             Long dpidLong, Long port ,
1701             List<Instruction> instructions) {
1702         NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
1703         LOG.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1704
1705         List<Action> actionList = Lists.newArrayList();
1706         ActionBuilder ab = new ActionBuilder();
1707
1708         List<Action> existingActions;
1709         if (instructions != null) {
1710             for (Instruction in : instructions) {
1711                 if (in.getInstruction() instanceof ApplyActionsCase) {
1712                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1713                     actionList.addAll(existingActions);
1714                 }
1715             }
1716         }
1717
1718         GroupBuilder groupBuilder = new GroupBuilder();
1719         Group group = null;
1720
1721         /* Create output action for this port*/
1722         OutputActionBuilder oab = new OutputActionBuilder();
1723         oab.setOutputNodeConnector(ncid);
1724         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
1725         LOG.debug("createOutputGroupInstructions(): output action {}", ab.build());
1726         boolean addNew = true;
1727         boolean groupActionAdded = false;
1728
1729         /* Find the group action and get the group */
1730         for (Action action : actionList) {
1731             if (action.getAction() instanceof GroupActionCase) {
1732                 groupActionAdded = true;
1733                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
1734                 Long id = groupAction.getGroupAction().getGroupId();
1735                 String groupName = groupAction.getGroupAction().getGroup();
1736                 GroupKey key = new GroupKey(new GroupId(id));
1737
1738                 groupBuilder.setGroupId(new GroupId(id));
1739                 groupBuilder.setGroupName(groupName);
1740                 groupBuilder.setGroupType(GroupTypes.GroupAll);
1741                 groupBuilder.setKey(key);
1742                 group = getGroup(groupBuilder, nodeBuilder);
1743                 LOG.debug("createOutputGroupInstructions: group {}", group);
1744                 break;
1745             }
1746         }
1747
1748         LOG.debug("createOutputGroupInstructions: groupActionAdded {}", groupActionAdded);
1749         if (groupActionAdded) {
1750             /* modify the action bucket in group */
1751             groupBuilder = new GroupBuilder(group);
1752             Buckets buckets = groupBuilder.getBuckets();
1753             for (Bucket bucket : buckets.getBucket()) {
1754                 List<Action> bucketActions = bucket.getAction();
1755                 LOG.debug("createOutputGroupInstructions: bucketActions {}", bucketActions);
1756                 for (Action action : bucketActions) {
1757                     if (action.getAction() instanceof OutputActionCase) {
1758                         OutputActionCase opAction = (OutputActionCase)action.getAction();
1759                         /* If output port action already in the action list of one of the buckets, skip */
1760                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1761                             addNew = false;
1762                             break;
1763                         }
1764                     }
1765                 }
1766             }
1767             LOG.debug("createOutputGroupInstructions: addNew {}", addNew);
1768             if (addNew && !buckets.getBucket().isEmpty()) {
1769                 /* the new output action is not in the bucket, add to bucket */
1770                 Bucket bucket = buckets.getBucket().get(0);
1771                 List<Action> bucketActionList = Lists.newArrayList();
1772                 bucketActionList.addAll(bucket.getAction());
1773                 /* set order for new action and add to action list */
1774                 ab.setOrder(bucketActionList.size());
1775                 ab.setKey(new ActionKey(bucketActionList.size()));
1776                 bucketActionList.add(ab.build());
1777
1778                 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
1779                 BucketsBuilder bucketsBuilder = new BucketsBuilder();
1780                 List<Bucket> bucketList = Lists.newArrayList();
1781                 BucketBuilder bucketBuilder = new BucketBuilder();
1782                 bucketBuilder.setBucketId(new BucketId((long) 1));
1783                 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
1784                 bucketBuilder.setAction(bucketActionList);
1785                 bucketList.add(bucketBuilder.build());
1786                 bucketsBuilder.setBucket(bucketList);
1787                 groupBuilder.setBuckets(bucketsBuilder.build());
1788                 LOG.debug("createOutputGroupInstructions: bucketList {}", bucketList);
1789             }
1790         } else {
1791             /* create group */
1792             groupBuilder = new GroupBuilder();
1793             groupBuilder.setGroupType(GroupTypes.GroupAll);
1794             groupBuilder.setGroupId(new GroupId(groupId));
1795             groupBuilder.setKey(new GroupKey(new GroupId(groupId)));
1796             groupBuilder.setGroupName("Output port group " + groupId);
1797             groupBuilder.setBarrier(false);
1798
1799             BucketsBuilder bucketBuilder = new BucketsBuilder();
1800             List<Bucket> bucketList = Lists.newArrayList();
1801             BucketBuilder bucket = new BucketBuilder();
1802             bucket.setBucketId(new BucketId((long) 1));
1803             bucket.setKey(new BucketKey(new BucketId((long) 1)));
1804
1805             /* put output action to the bucket */
1806             List<Action> bucketActionList = Lists.newArrayList();
1807             /* set order for new action and add to action list */
1808             ab.setOrder(bucketActionList.size());
1809             ab.setKey(new ActionKey(bucketActionList.size()));
1810             bucketActionList.add(ab.build());
1811
1812             bucket.setAction(bucketActionList);
1813             bucketList.add(bucket.build());
1814             bucketBuilder.setBucket(bucketList);
1815             groupBuilder.setBuckets(bucketBuilder.build());
1816
1817             /* Add new group action */
1818             GroupActionBuilder groupActionB = new GroupActionBuilder();
1819             groupActionB.setGroupId(groupId);
1820             groupActionB.setGroup("Output port group " + groupId);
1821             ab = new ActionBuilder();
1822             ab.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionB.build()).build());
1823             ab.setOrder(actionList.size());
1824             ab.setKey(new ActionKey(actionList.size()));
1825             actionList.add(ab.build());
1826
1827             groupId++;
1828         }
1829         LOG.debug("createOutputGroupInstructions: group {}", groupBuilder.build());
1830         LOG.debug("createOutputGroupInstructions: actionList {}", actionList);
1831
1832         if (addNew) {
1833             /* rewrite the group to group table */
1834             writeGroup(groupBuilder, nodeBuilder);
1835         }
1836
1837         // Create an Apply Action
1838         ApplyActionsBuilder aab = new ApplyActionsBuilder();
1839         aab.setAction(actionList);
1840         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1841
1842         return ib;
1843     }
1844
1845     /**
1846      * Remove Output Port from action list in group bucket
1847      *
1848      * @param ib       Map InstructionBuilder without any instructions
1849      * @param dpidLong Long the datapath ID of a switch/node
1850      * @param port     Long representing a port on a switch/node
1851      * @return ib InstructionBuilder Map with instructions
1852      */
1853     // TODO This method is referenced from commented code in L2ForwardingService (which needs to be checked)
1854     @SuppressWarnings("unused")
1855     protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
1856             Long dpidLong, Long port , List<Instruction> instructions) {
1857
1858         NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
1859         LOG.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1860
1861         List<Action> actionList = Lists.newArrayList();
1862         ActionBuilder ab;
1863
1864         List<Action> existingActions;
1865         if (instructions != null) {
1866             for (Instruction in : instructions) {
1867                 if (in.getInstruction() instanceof ApplyActionsCase) {
1868                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1869                     actionList.addAll(existingActions);
1870                     break;
1871                 }
1872             }
1873         }
1874
1875         GroupBuilder groupBuilder = new GroupBuilder();
1876         Group group = null;
1877         boolean groupActionAdded = false;
1878         /* Find the group action and get the group */
1879         for (Action action : actionList) {
1880             if (action.getAction() instanceof GroupActionCase) {
1881                 groupActionAdded = true;
1882                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
1883                 Long id = groupAction.getGroupAction().getGroupId();
1884                 String groupName = groupAction.getGroupAction().getGroup();
1885                 GroupKey key = new GroupKey(new GroupId(id));
1886
1887                 groupBuilder.setGroupId(new GroupId(id));
1888                 groupBuilder.setGroupName(groupName);
1889                 groupBuilder.setGroupType(GroupTypes.GroupAll);
1890                 groupBuilder.setKey(key);
1891                 group = getGroup(groupBuilder, nodeBuilder);
1892                 break;
1893             }
1894         }
1895
1896         if (groupActionAdded) {
1897             /* modify the action bucket in group */
1898             groupBuilder = new GroupBuilder(group);
1899             Buckets buckets = groupBuilder.getBuckets();
1900             List<Action> bucketActions = Lists.newArrayList();
1901             for (Bucket bucket : buckets.getBucket()) {
1902                 int index = 0;
1903                 boolean isPortDeleted = false;
1904                 bucketActions = bucket.getAction();
1905                 for (Action action : bucketActions) {
1906                     if (action.getAction() instanceof OutputActionCase) {
1907                         OutputActionCase opAction = (OutputActionCase)action.getAction();
1908                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1909                             /* Find the output port in action list and remove */
1910                             index = bucketActions.indexOf(action);
1911                             bucketActions.remove(action);
1912                             isPortDeleted = true;
1913                             break;
1914                         }
1915                     }
1916                 }
1917                 if (isPortDeleted && !bucketActions.isEmpty()) {
1918                     for (int i = index; i< bucketActions.size(); i++) {
1919                         Action action = bucketActions.get(i);
1920                         if (action.getOrder() != i) {
1921                             /* Shift the action order */
1922                             ab = new ActionBuilder();
1923                             ab.setAction(action.getAction());
1924                             ab.setOrder(i);
1925                             ab.setKey(new ActionKey(i));
1926                             Action actionNewOrder = ab.build();
1927                             bucketActions.remove(action);
1928                             bucketActions.add(i, actionNewOrder);
1929                         }
1930                     }
1931
1932                 } else if (bucketActions.isEmpty()) {
1933                     /* remove bucket with empty action list */
1934                     buckets.getBucket().remove(bucket);
1935                     break;
1936                 }
1937             }
1938             if (!buckets.getBucket().isEmpty()) {
1939                 /* rewrite the group to group table */
1940                 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
1941                 BucketsBuilder bucketsBuilder = new BucketsBuilder();
1942                 List<Bucket> bucketList = Lists.newArrayList();
1943                 BucketBuilder bucketBuilder = new BucketBuilder();
1944                 bucketBuilder.setBucketId(new BucketId((long) 1));
1945                 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
1946                 bucketBuilder.setAction(bucketActions);
1947                 bucketList.add(bucketBuilder.build());
1948                 bucketsBuilder.setBucket(bucketList);
1949                 groupBuilder.setBuckets(bucketsBuilder.build());
1950                 LOG.debug("removeOutputPortFromGroup: bucketList {}", bucketList);
1951
1952                 writeGroup(groupBuilder, nodeBuilder);
1953                 ApplyActionsBuilder aab = new ApplyActionsBuilder();
1954                 aab.setAction(actionList);
1955                 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1956                 return false;
1957             } else {
1958                 /* remove group with empty bucket. return true to delete flow */
1959                 removeGroup(groupBuilder, nodeBuilder);
1960                 return true;
1961             }
1962         } else {
1963             /* no group for port list. flow can be removed */
1964             return true;
1965         }
1966     }
1967
1968     @Override
1969     public void initializeOFFlowRules(Node openflowNode) {
1970         String bridgeName = southbound.getBridgeName(openflowNode);
1971         LOG.info("initializeOFFlowRules: bridgeName: {}", bridgeName);
1972         if (bridgeName.equals(configurationService.getIntegrationBridgeName())) {
1973             initializeFlowRules(openflowNode, configurationService.getIntegrationBridgeName());
1974             triggerInterfaceUpdates(openflowNode);
1975         } else if (bridgeName.equals(configurationService.getExternalBridgeName())) {
1976             initializeFlowRules(openflowNode, configurationService.getExternalBridgeName());            
1977             triggerInterfaceUpdates(openflowNode);
1978         }
1979     }
1980
1981     public static NodeBuilder createNodeBuilder(String nodeId) {
1982         NodeBuilder builder = new NodeBuilder();
1983         builder.setId(new NodeId(nodeId));
1984         builder.setKey(new NodeKey(builder.getId()));
1985         return builder;
1986     }
1987
1988     @Override
1989     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1990         this.bundleContext = bundleContext;
1991         configurationService =
1992                 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
1993         tenantNetworkManager =
1994                 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
1995         bridgeConfigurationManager =
1996                 (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this);
1997         nodeCacheManager =
1998                 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
1999         classifierProvider =
2000                 (ClassifierProvider) ServiceHelper.getGlobalInstance(ClassifierProvider.class, this);
2001         ingressAclProvider =
2002                 (IngressAclProvider) ServiceHelper.getGlobalInstance(IngressAclProvider.class, this);
2003         egressAclProvider =
2004                 (EgressAclProvider) ServiceHelper.getGlobalInstance(EgressAclProvider.class, this);
2005         l2ForwardingProvider =
2006                 (L2ForwardingProvider) ServiceHelper.getGlobalInstance(L2ForwardingProvider.class, this);
2007         securityServicesManager =
2008                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
2009         southbound =
2010                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
2011     }
2012
2013     @Override
2014     public void setDependencies(Object impl) {
2015         if (impl instanceof NetworkingProviderManager) {
2016             NetworkingProviderManager networkingProviderManager = (NetworkingProviderManager) impl;
2017             networkingProviderManager.providerAdded(
2018                     bundleContext.getServiceReference(NetworkingProvider.class.getName()), this);
2019         }
2020     }
2021 }