Use initFlowBuilder for LoadBalancerService
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / LoadBalancerService.java
1 /*
2  * Copyright (c) 2014 SDN Hub, LLC. 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 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
9
10 import java.math.BigInteger;
11 import java.util.List;
12 import java.util.Map;
13
14 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
15 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration.LoadBalancerPoolMember;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
22 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
23 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
24 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
25 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
26 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
27 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
28 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxHashFields;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxMpAlgorithm;
54 import org.osgi.framework.BundleContext;
55 import org.osgi.framework.ServiceReference;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import com.google.common.collect.Lists;
60
61 public class LoadBalancerService extends AbstractServiceInstance implements LoadBalancerProvider, ConfigInterface {
62
63     private static final Logger LOG = LoggerFactory.getLogger(LoadBalancerProvider.class);
64     private static final int DEFAULT_FLOW_PRIORITY = 32768;
65     private static final Long FIRST_PASS_REGA_MATCH_VALUE = 0L;
66     private static final Long SECOND_PASS_REGA_MATCH_VALUE = 1L;
67
68     private static final Class<? extends NxmNxReg> REG_FIELD_A = NxmNxReg1.class;
69     private static final Class<? extends NxmNxReg> REG_FIELD_B = NxmNxReg2.class;
70     
71     private volatile Southbound southbound;
72
73     public LoadBalancerService() {
74         super(Service.LOAD_BALANCER);
75     }
76
77     public LoadBalancerService(Service service) {
78         super(service);
79     }
80
81     private String getDpid(Node node) {
82         long dpid = southbound.getDataPathId(node);
83         if (dpid == 0) {
84             LOG.warn("getDpid: DPID could not be found for node: {}", node.getNodeId().getValue());
85         }
86         return String.valueOf(dpid);
87     }
88     
89     /**
90      * When this method is called, we do the following for minimizing flow updates:
91      * 1. Overwrite the solo multipath rule that applies to all members
92      * 2. Append second pass rule for the header rewriting specific to this member
93      * 3. Append reverse rules specific to this member
94      */
95     @Override
96     public Status programLoadBalancerPoolMemberRules(Node node,
97                                                      LoadBalancerConfiguration lbConfig, LoadBalancerPoolMember member,
98                                                      org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
99         if (lbConfig == null || member == null) {
100             LOG.error("Null value for LB config {} or Member {}", lbConfig, member);
101             return new Status(StatusCode.BADREQUEST);
102         }
103         if (!lbConfig.isValid()) {
104             LOG.error("LB config is invalid: {}", lbConfig);
105             return new Status(StatusCode.BADREQUEST);
106         }
107         LOG.debug("Performing {} rules for member {} with index {} on LB with VIP {} and total members {}",
108                 action, member.getIP(), member.getIndex(), lbConfig.getVip(), lbConfig.getMembers().size());
109
110         NodeBuilder nodeBuilder = new NodeBuilder();
111         nodeBuilder.setId(new NodeId(Constants.OPENFLOW_NODE_PREFIX + getDpid(node)));
112         nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
113
114         //Update the multipath rule
115         manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, true);
116
117         if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.ADD)) {
118             manageLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig, member, true);
119             manageLoadBalancerMemberReverseRules(nodeBuilder, lbConfig, member, true);
120             return new Status(StatusCode.SUCCESS);
121         }
122         /* TODO: Delete single member.
123          * For now, removing a member requires deleting the full LB instance and re-adding
124          */
125         return new Status(StatusCode.NOTIMPLEMENTED);
126     }
127
128     /**
129      * When this method is called, we perform the following:
130      * 1. Write the solo multipath rule that applies to all members
131      * 2. Append second pass rules for the header rewriting for all members
132      * 3. Append reverse rules for all the members, specific to the protocol/port
133      */
134     @Override
135     public Status programLoadBalancerRules(Node node, LoadBalancerConfiguration lbConfig,
136                                            org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
137         if (lbConfig == null || !lbConfig.isValid()) {
138             LOG.error("LB config is invalid: {}", lbConfig);
139             return new Status(StatusCode.BADREQUEST);
140         }
141         LOG.debug("Performing {} rules for VIP {} and {} members", action, lbConfig.getVip(), lbConfig.getMembers().size());
142
143         NodeBuilder nodeBuilder = new NodeBuilder();
144         nodeBuilder.setId(new NodeId(Constants.OPENFLOW_NODE_PREFIX + getDpid(node)));
145         nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
146
147         if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.ADD)) {
148             manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, true);
149             manageLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig, true);
150             manageLoadBalancerReverseRules(nodeBuilder, lbConfig, true);
151             return new Status(StatusCode.SUCCESS);
152         }
153         else if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.DELETE)) {
154             manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, false);
155             manageLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig, false);
156             manageLoadBalancerReverseRules(nodeBuilder, lbConfig, false);
157             return new Status(StatusCode.SUCCESS);
158         }
159
160         return new Status(StatusCode.NOTIMPLEMENTED);
161     }
162
163     /**
164      * Method to insert/remove default rule for traffic destined to the VIP and no
165      * server selection performed yet
166      * @param nodeBuilder NodeBuilder
167      * @param lbConfig LoadBalancerConfiguration
168      * @param write Boolean to indicate of the flow is to be inserted or removed
169      */
170     private void manageLoadBalancerVIPRulesFirstPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig,
171                                                      boolean write) {
172         FlowBuilder flowBuilder = new FlowBuilder();
173         String flowName = "LOADBALANCER_FORWARD_FLOW1_" + lbConfig.getProviderSegmentationId() + "_" + lbConfig.getVip();
174         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(DEFAULT_FLOW_PRIORITY);
175
176         MatchBuilder matchBuilder = new MatchBuilder();
177
178         // Match Tunnel-ID, VIP, and Reg0==0
179         if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
180             lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
181             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
182         } else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
183             MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
184         } else {
185             return; //Should not get here. TODO: Other types
186         }
187
188         MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(lbConfig.getVip()));
189         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, FIRST_PASS_REGA_MATCH_VALUE));
190         flowBuilder.setMatch(matchBuilder.build());
191
192         if (write) {
193             // Create the OF Actions and Instructions
194             InstructionsBuilder isb = new InstructionsBuilder();
195
196             // Instructions List Stores Individual Instructions
197             List<Instruction> instructions = Lists.newArrayList();
198
199             List<Action> actionList = Lists.newArrayList();
200
201             ActionBuilder ab = new ActionBuilder();
202             ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD_A).build(),
203                     BigInteger.valueOf(SECOND_PASS_REGA_MATCH_VALUE)));
204             ab.setOrder(0);
205             ab.setKey(new ActionKey(0));
206             actionList.add(ab.build());
207
208             ab = new ActionBuilder();
209             ab.setAction(ActionUtils.nxMultipathAction(OfjNxHashFields.NXHASHFIELDSSYMMETRICL4,
210                     0, OfjNxMpAlgorithm.NXMPALGMODULON,
211                     lbConfig.getMembers().size()-1, //By Nicira-Ext spec, this field is max_link minus 1
212                     0L, new DstNxRegCaseBuilder().setNxReg(REG_FIELD_B).build(),
213                     0, 31));
214             ab.setOrder(1);
215             ab.setKey(new ActionKey(1));
216             actionList.add(ab.build());
217
218             ab = new ActionBuilder();
219             ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
220             ab.setOrder(2);
221             ab.setKey(new ActionKey(2));
222             actionList.add(ab.build());
223
224             // Create an Apply Action
225             ApplyActionsBuilder aab = new ApplyActionsBuilder();
226             aab.setAction(actionList);
227             InstructionBuilder ib = new InstructionBuilder();
228             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
229
230             // Call the InstructionBuilder Methods Containing Actions
231             ib.setOrder(0);
232             ib.setKey(new InstructionKey(0));
233             instructions.add(ib.build());
234
235             // Add InstructionBuilder to the Instruction(s)Builder List
236             isb.setInstruction(instructions);
237
238             // Add InstructionsBuilder to FlowBuilder
239             flowBuilder.setInstructions(isb.build());
240
241             writeFlow(flowBuilder, nodeBuilder);
242         } else {
243             removeFlow(flowBuilder, nodeBuilder);
244         }
245     }
246
247     /*
248      * Method to program each rule that matches on Reg0 and Reg1 to insert appropriate header rewriting
249      * rules for all members. This function calls manageLoadBalancerMemberVIPRulesSecondPass in turn.
250      * @param nodeBuilder Node to insert rule to
251      * @param lbConfig Configuration for this LoadBalancer instance
252      * @param write Boolean to indicate of the flow is to be inserted or removed
253      */
254     private void manageLoadBalancerVIPRulesSecondPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
255         for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
256             manageLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig, entry.getValue(), write);
257         }
258     }
259
260     private void manageLoadBalancerMemberVIPRulesSecondPass(NodeBuilder nodeBuilder,
261                                                             LoadBalancerConfiguration lbConfig,
262                                                             LoadBalancerPoolMember member, boolean write) {
263         String vip = lbConfig.getVip();
264
265         FlowBuilder flowBuilder = new FlowBuilder();
266         String flowName = "LOADBALANCER_FORWARD_FLOW2_" + lbConfig.getProviderSegmentationId() + "_"
267                 + vip + "_" + member.getIP();
268         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(DEFAULT_FLOW_PRIORITY+1);
269
270         MatchBuilder matchBuilder = new MatchBuilder();
271
272         // Match Tunnel-ID, VIP, Reg0==1 and Reg1==Index of member
273         if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
274             lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
275             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
276         } else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
277             MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
278         } else {
279             return; //Should not get here. TODO: Other types
280         }
281
282         MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(vip));
283         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, SECOND_PASS_REGA_MATCH_VALUE),
284                                                new MatchUtils.RegMatch(REG_FIELD_B, (long)member.getIndex()));
285         flowBuilder.setMatch(matchBuilder.build());
286
287         if (write) {
288             // Create the OF Actions and Instructions
289             InstructionsBuilder isb = new InstructionsBuilder();
290
291             // Instructions List Stores Individual Instructions
292             List<Instruction> instructions = Lists.newArrayList();
293
294             List<Action> actionList = Lists.newArrayList();
295             ActionBuilder ab = new ActionBuilder();
296             ab.setAction(ActionUtils.setDlDstAction(new MacAddress(member.getMAC())));
297             ab.setOrder(0);
298             ab.setKey(new ActionKey(0));
299             actionList.add(ab.build());
300
301             ab = new ActionBuilder();
302             Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(MatchUtils.iPv4PrefixFromIPv4Address(member.getIP()));
303             ab.setAction(ActionUtils.setNwDstAction(ipb.build()));
304             ab.setOrder(1);
305             ab.setKey(new ActionKey(1));
306             actionList.add(ab.build());
307
308             // Create an Apply Action
309             ApplyActionsBuilder aab = new ApplyActionsBuilder();
310             aab.setAction(actionList);
311
312             // Call the InstructionBuilder Methods Containing Actions
313             InstructionBuilder ib = new InstructionBuilder();
314             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
315             ib.setOrder(0);
316             ib.setKey(new InstructionKey(0));
317             instructions.add(ib.build());
318
319             // Call the InstructionBuilder Methods Containing Actions
320             ib = this.getMutablePipelineInstructionBuilder();
321             ib.setOrder(1);
322             ib.setKey(new InstructionKey(1));
323             instructions.add(ib.build());
324
325             // Add InstructionBuilder to the Instruction(s)Builder List
326             isb.setInstruction(instructions);
327
328             // Add InstructionsBuilder to FlowBuilder
329             flowBuilder.setInstructions(isb.build());
330
331             writeFlow(flowBuilder, nodeBuilder);
332         } else {
333             removeFlow(flowBuilder, nodeBuilder);
334         }
335     }
336
337     /**
338      * Method to program all reverse rules that matches member {IP, Protocol, Port} for all members.
339      * This function calls manageLoadBalancerMemberReverseRules in turn.
340      * @param nodeBuilder Node to insert rule to
341      * @param lbConfig Configuration for this LoadBalancer instance
342      */
343     private void manageLoadBalancerReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
344         for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
345             manageLoadBalancerMemberReverseRules(nodeBuilder, lbConfig, entry.getValue(), write);
346         }
347     }
348
349     private void manageLoadBalancerMemberReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig,
350             LoadBalancerPoolMember member, boolean write) {
351
352         String vip = lbConfig.getVip();
353         String vmac = lbConfig.getVmac();
354
355         FlowBuilder flowBuilder = new FlowBuilder();
356         String flowName = "LOADBALANCER_REVERSE_FLOW_" + lbConfig.getProviderSegmentationId() +
357                 vip + "_" + member.getIP();
358         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(DEFAULT_FLOW_PRIORITY);
359
360         MatchBuilder matchBuilder = new MatchBuilder();
361
362         // Match Tunnel-ID, MemberIP, and Protocol/Port
363         if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
364                    lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
365             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
366         } else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
367             MatchUtils.createVlanIdMatch(matchBuilder,
368                     new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
369         } else {
370             return; //Should not get here. TODO: Other types
371         }
372
373         MatchUtils.createSrcL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(member.getIP()));
374         MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(member.getPort()));
375         flowBuilder.setMatch(matchBuilder.build());
376
377         if (write) {
378             // Create the OF Actions and Instructions
379             InstructionsBuilder isb = new InstructionsBuilder();
380
381             // Instructions List Stores Individual Instructions
382             List<Instruction> instructions = Lists.newArrayList();
383
384             List<Action> actionList = Lists.newArrayList();
385             ActionBuilder ab = new ActionBuilder();
386             Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(MatchUtils.iPv4PrefixFromIPv4Address(vip));
387             ab.setAction(ActionUtils.setNwSrcAction(ipb.build()));
388             ab.setOrder(0);
389             ab.setKey(new ActionKey(0));
390             actionList.add(ab.build());
391
392             /* If a dummy MAC is assigned to the VIP, we use that as the
393              * source MAC for the reverse traffic.
394              */
395             if (vmac != null) {
396                 ab = new ActionBuilder();
397                 ab.setAction(ActionUtils.setDlDstAction(new MacAddress(vmac)));
398                 ab.setOrder(1);
399                 ab.setKey(new ActionKey(1));
400                 actionList.add(ab.build());
401             }
402
403             // Create an Apply Action
404             ApplyActionsBuilder aab = new ApplyActionsBuilder();
405             aab.setAction(actionList);
406
407             // Call the InstructionBuilder Methods Containing Actions
408             InstructionBuilder ib = new InstructionBuilder();
409             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
410             ib.setOrder(0);
411             ib.setKey(new InstructionKey(0));
412             instructions.add(ib.build());
413
414             // Call the InstructionBuilder Methods Containing Actions
415             ib = this.getMutablePipelineInstructionBuilder();
416             ib.setOrder(1);
417             ib.setKey(new InstructionKey(1));
418             instructions.add(ib.build());
419
420             // Add InstructionBuilder to the Instruction(s)Builder List
421             isb.setInstruction(instructions);
422
423             // Add InstructionsBuilder to FlowBuilder
424             flowBuilder.setInstructions(isb.build());
425
426             writeFlow(flowBuilder, nodeBuilder);
427         } else {
428             removeFlow(flowBuilder, nodeBuilder);
429         }
430     }
431
432     @Override
433     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
434         super.setDependencies(bundleContext.getServiceReference(LoadBalancerProvider.class.getName()), this);
435         southbound =(Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
436     }
437
438     @Override
439     public void setDependencies(Object impl) {
440
441     }
442 }