Use Java declarations instead of Google Collections
[netvirt.git] / openstack / net-virt-sfc / impl / src / main / java / org / opendaylight / netvirt / openstack / netvirt / sfc / workaround / services / SfcClassifierService.java
1 /*
2  * Copyright © 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.sfc.workaround.services;
10
11 import com.google.common.util.concurrent.CheckedFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Map;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
21 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
22 import org.opendaylight.netvirt.openstack.netvirt.sfc.NshUtils;
23 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
24 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
25 import org.opendaylight.netvirt.openstack.netvirt.sfc.ISfcClassifierService;
26 import org.opendaylight.netvirt.utils.mdsal.openflow.ActionUtils;
27 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
28 import org.opendaylight.netvirt.utils.mdsal.openflow.InstructionUtils;
29 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.osgi.framework.BundleContext;
52 import org.osgi.framework.ServiceReference;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface, ISfcClassifierService {
57     private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class);
58     private static final short UDP_SHORT = 17;
59     static int cookieIndex = 0;
60     private FlowCache flowCache = new FlowCache();
61
62     private enum FlowID {
63         FLOW_INGRESSCLASS(1), FLOW_SFINGRESS(2), FLOW_SFEGRESS(3), FLOW_SFARP(4),
64         FLOW_EGRESSCLASSUNUSED(5), FLOW_EGRESSCLASS(6), FLOW_EGRESSCLASSBYPASS(7), FLOW_SFCTABLE(8);
65
66         private int value;
67         FlowID(int value) {
68             this.value = value;
69         }
70     }
71
72     private BigInteger getCookie(FlowID flowID) {
73         String cookieString = String.format("1110%02d%010d", flowID.value, cookieIndex++);
74         return new BigInteger(cookieString, 16);
75     }
76
77     private BigInteger getCookie(FlowID flowID, short nsp, short nsi) {
78         String cookieString = String.format("1110%02d%03d%03d0%03d", flowID.value, 0, nsp, nsi);
79         return new BigInteger(cookieString, 16);
80     }
81
82     public SfcClassifierService(Service service) {
83         super(service);
84     }
85
86     public SfcClassifierService() {
87         super(Service.SFC_CLASSIFIER);
88     }
89
90     @Override
91     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
92         super.setDependencies(bundleContext.getServiceReference(ISfcClassifierService.class.getName()), this);
93     }
94
95     @Override
96     public void setDependencies(Object impl) {}
97
98     private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID) {
99         FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
100                 .setCookie(new FlowCookie(getCookie(flowID)))
101                 .setCookieMask(new FlowCookie(getCookie(flowID)));
102         return flowBuilder;
103     }
104
105     private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID,
106                                         short nsp, short nsi) {
107         FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
108                 .setCookie(new FlowCookie(getCookie(flowID, nsp, nsi)))
109                 .setCookieMask(new FlowCookie(getCookie(flowID, nsp, nsi)));
110         return flowBuilder;
111     }
112
113     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder, String rspName, FlowID flowID) {
114         flowCache.addFlow(flowBuilder, nodeBuilder, rspName, flowID.value);
115         writeFlow(flowBuilder, nodeBuilder);
116     }
117
118     private void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder, String rspName, FlowID flowID) {
119         flowCache.removeFlow(rspName, flowID.value);
120         removeFlow(flowBuilder, nodeBuilder);
121     }
122
123     @Override
124     public void programIngressClassifier(long dataPathId, String ruleName, Matches matches, long nsp, short nsi,
125                                          NshUtils nshHeader, long vxGpeOfPort, String rspName, boolean write) {
126         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
127         FlowBuilder flowBuilder = new FlowBuilder();
128         String flowName = FlowNames.getSfcIngressClass(ruleName, nsp, nsi);
129         initFlowBuilder(flowBuilder, flowName, getTable(), FlowID.FLOW_INGRESSCLASS,
130                 (short)nshHeader.getNshNsp(), nshHeader.getNshNsi());
131
132         MatchBuilder matchBuilder = new AclMatches(matches).buildMatch();
133         MatchUtils.addNxRegMatch(matchBuilder,
134                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
135         flowBuilder.setMatch(matchBuilder.build());
136
137         if (write) {
138             ActionBuilder ab = new ActionBuilder();
139             List<Action> actionList = new ArrayList<>();
140
141             ab.setAction(ActionUtils.nxMoveTunIdtoNshc2());
142             ab.setOrder(actionList.size());
143             ab.setKey(new ActionKey(actionList.size()));
144             actionList.add(ab.build());
145
146             getNshAction(nshHeader, actionList);
147
148             if (vxGpeOfPort != 0) {
149                 ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(dataPathId, vxGpeOfPort)));
150                 ab.setOrder(actionList.size());
151                 ab.setKey(new ActionKey(actionList.size()));
152                 actionList.add(ab.build());
153             } else {
154                 ab.setAction(ActionUtils.nxResubmitAction(null, Service.CLASSIFIER.getTable()));
155                 ab.setOrder(actionList.size());
156                 ab.setKey(new ActionKey(actionList.size()));
157                 actionList.add(ab.build());
158             }
159
160             ApplyActionsBuilder aab = new ApplyActionsBuilder();
161             aab.setAction(actionList);
162
163             InstructionBuilder ib = new InstructionBuilder();
164             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
165             ib.setOrder(0);
166             ib.setKey(new InstructionKey(0));
167             List<Instruction> instructions = new ArrayList<>();
168             instructions.add(ib.build());
169
170             InstructionsBuilder isb = new InstructionsBuilder();
171             isb.setInstruction(instructions);
172             flowBuilder.setInstructions(isb.build());
173             writeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_INGRESSCLASS);
174         } else {
175             removeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_INGRESSCLASS);
176         }
177     }
178
179     @Override
180     public void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write) {
181         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
182         FlowBuilder flowBuilder = new FlowBuilder();
183         String flowName = FlowNames.getSfcTable(vxGpeOfPort);
184         initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER), FlowID.FLOW_SFCTABLE)
185                 .setPriority(1000);
186
187         MatchBuilder matchBuilder = new MatchBuilder();
188         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
189         flowBuilder.setMatch(matchBuilder.build());
190
191         if (write) {
192             InstructionsBuilder isb = new InstructionsBuilder();
193             List<Instruction> instructions = new ArrayList<>();
194             InstructionBuilder ib =
195                     InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), goToTableId);
196             ib.setOrder(0);
197             ib.setKey(new InstructionKey(0));
198             instructions.add(ib.build());
199
200             isb.setInstruction(instructions);
201             flowBuilder.setInstructions(isb.build());
202             writeFlow(flowBuilder, nodeBuilder);
203         } else {
204             removeFlow(flowBuilder, nodeBuilder);
205         }
206     }
207
208     @Override
209     public void programEgressClassifier1(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
210                                          int tunnelOfPort, int tunnelId, short gotoTableId, boolean write) {
211         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
212         FlowBuilder flowBuilder = new FlowBuilder();
213         String flowName = FlowNames.getSfcEgressClass1(vxGpeOfPort);
214         initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER), FlowID.FLOW_EGRESSCLASSUNUSED,
215                 (short)nsp, nsi);
216
217         MatchBuilder matchBuilder = new MatchBuilder();
218         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
219         MatchUtils.addNxNspMatch(matchBuilder, nsp);
220         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
221         flowBuilder.setMatch(matchBuilder.build());
222
223         if (write) {
224             InstructionsBuilder isb = new InstructionsBuilder();
225             List<Instruction> instructions = new ArrayList<>();
226
227             InstructionBuilder ib = InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), getTable());
228             ib.setOrder(instructions.size());
229             ib.setKey(new InstructionKey(instructions.size()));
230             instructions.add(ib.build());
231
232             isb.setInstruction(instructions);
233             flowBuilder.setInstructions(isb.build());
234             writeFlow(flowBuilder, nodeBuilder);
235         } else {
236             removeFlow(flowBuilder, nodeBuilder);
237         }
238     }
239
240     @Override
241     public void programEgressClassifier(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
242                                         long sfOfPort, int tunnelId, String rspName, boolean write) {
243         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
244         FlowBuilder flowBuilder = new FlowBuilder();
245         String flowName = FlowNames.getSfcEgressClass(vxGpeOfPort, nsp, nsi);
246         initFlowBuilder(flowBuilder, flowName, getTable(Service.SFC_CLASSIFIER), FlowID.FLOW_EGRESSCLASS,
247                 (short)nsp, nsi);
248
249         MatchBuilder matchBuilder = new MatchBuilder();
250         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
251         MatchUtils.addNxNspMatch(matchBuilder, nsp);
252         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
253         flowBuilder.setMatch(matchBuilder.build());
254
255         if (write) {
256             InstructionsBuilder isb = new InstructionsBuilder();
257             List<Instruction> instructions = new ArrayList<>();
258             List<Action> actionList = new ArrayList<>();
259
260             ActionBuilder ab = new ActionBuilder();
261
262             ab.setAction(
263                     ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(FlowUtils.REG_FIELD).build(),
264                     BigInteger.valueOf(FlowUtils.REG_VALUE_FROM_LOCAL)));
265             ab.setOrder(actionList.size());
266             ab.setKey(new ActionKey(actionList.size()));
267             actionList.add(ab.build());
268
269             ab.setAction(ActionUtils.nxMoveNshc2ToTunId());
270             ab.setOrder(actionList.size());
271             ab.setKey(new ActionKey(actionList.size()));
272             actionList.add(ab.build());
273
274             ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, getTable(Service.CLASSIFIER)));
275             ab.setOrder(actionList.size());
276             ab.setKey(new ActionKey(actionList.size()));
277             actionList.add(ab.build());
278
279             ApplyActionsBuilder aab = new ApplyActionsBuilder();
280             aab.setAction(actionList);
281             InstructionBuilder ib = new InstructionBuilder();
282             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
283
284             ib.setOrder(0);
285             ib.setKey(new InstructionKey(0));
286             instructions.add(ib.build());
287
288             isb.setInstruction(instructions);
289             flowBuilder.setInstructions(isb.build());
290             writeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_EGRESSCLASS);
291         } else {
292             removeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_EGRESSCLASS);
293         }
294     }
295
296     @Override
297     public void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
298                                               long sfOfPort, int tunnelId, String rspName, boolean write) {
299         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
300         FlowBuilder flowBuilder = new FlowBuilder();
301         String flowName = FlowNames.getSfcEgressClassBypass(nsp, nsi, sfOfPort);
302         initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER),
303                 FlowID.FLOW_EGRESSCLASSBYPASS, (short)nsp, nsi)
304                 .setPriority(40000);
305
306         MatchBuilder matchBuilder = new MatchBuilder();
307         MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort);
308         MatchUtils.addNxRegMatch(matchBuilder,
309                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
310         MatchUtils.addNxNspMatch(matchBuilder, nsp);
311         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
312         flowBuilder.setMatch(matchBuilder.build());
313
314         if (write) {
315             ActionBuilder ab = new ActionBuilder();
316             org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action popNshAction =
317                 ActionUtils.nxPopNshAction();
318             ab.setAction(popNshAction);
319             ab.setOrder(0);
320             ab.setKey(new ActionKey(0));
321
322             List<Action> actionList = new ArrayList<>();
323             actionList.add(ab.build());
324
325             ApplyActionsBuilder aab = new ApplyActionsBuilder();
326             aab.setAction(actionList);
327
328             InstructionBuilder popNshIb = new InstructionBuilder();
329             popNshIb.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
330             popNshIb.setOrder(0);
331             popNshIb.setKey(new InstructionKey(0));
332
333             // This will do a goto table
334             InstructionBuilder mutableIb;
335             mutableIb = this.getMutablePipelineInstructionBuilder();
336             mutableIb.setOrder(1);
337             mutableIb.setKey(new InstructionKey(1));
338
339             List<Instruction> instructions = new ArrayList<>();
340             instructions.add(popNshIb.build());
341             instructions.add(mutableIb.build());
342
343             InstructionsBuilder isb = new InstructionsBuilder();
344             isb.setInstruction(instructions);
345             flowBuilder.setInstructions(isb.build());
346             writeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_EGRESSCLASSBYPASS);
347         } else {
348             removeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_EGRESSCLASSBYPASS);
349         }
350     }
351
352     // packet from sf to sff that need to go out local
353     @Override
354     public void program_sfEgress(long dataPathId, int dstPort, String rspName, boolean write) {
355         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
356         FlowBuilder flowBuilder = new FlowBuilder();
357         String flowName = FlowNames.getSfEgress(dstPort);
358         initFlowBuilder(flowBuilder, flowName, getTable(), FlowID.FLOW_SFEGRESS);
359
360         MatchBuilder matchBuilder = new MatchBuilder();
361         MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
362         MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
363         MatchUtils.addNxRegMatch(matchBuilder,
364                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
365         flowBuilder.setMatch(matchBuilder.build());
366
367         if (write) {
368             InstructionBuilder ib = new InstructionBuilder();
369             InstructionsBuilder isb = new InstructionsBuilder();
370             List<Instruction> instructions = new ArrayList<>();
371             InstructionUtils.createLocalInstructions(ib, dataPathId);
372             ib.setOrder(0);
373             ib.setKey(new InstructionKey(0));
374             instructions.add(ib.build());
375
376             isb.setInstruction(instructions);
377             flowBuilder.setInstructions(isb.build());
378             writeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_SFEGRESS);
379         } else {
380             removeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_SFEGRESS);
381         }
382     }
383
384     // looped back sff to sf packets
385     @Override
386     public void program_sfIngress(long dataPathId, int dstPort, long sfOfPort,
387                                   String ipAddress, String sfDplName, String rspName, boolean write) {
388         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
389         FlowBuilder flowBuilder = new FlowBuilder();
390         String flowName = FlowNames.getSfIngress(dstPort, ipAddress);
391         initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFINGRESS);
392
393         MatchBuilder matchBuilder = new MatchBuilder();
394         MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
395         Ipv4Prefix ipCidr = MatchUtils.iPv4PrefixFromIPv4Address(ipAddress);
396         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(ipCidr));
397         MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
398         flowBuilder.setMatch(matchBuilder.build());
399
400         if (write) {
401             InstructionBuilder ib = new InstructionBuilder();
402             InstructionsBuilder isb = new InstructionsBuilder();
403             List<Instruction> instructions = new ArrayList<>();
404             InstructionUtils.createOutputPortInstructions(ib, dataPathId, sfOfPort);
405
406             ib.setOrder(0);
407             ib.setKey(new InstructionKey(0));
408             instructions.add(ib.build());
409
410             isb.setInstruction(instructions);
411             flowBuilder.setInstructions(isb.build());
412             writeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_SFINGRESS);
413         } else {
414             removeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_SFINGRESS);
415         }
416     }
417
418     @Override
419     public void programStaticArpEntry(long dataPathId, long ofPort, String macAddressStr,
420                                       String ipAddress, String rspName, boolean write) {
421         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
422         FlowBuilder flowBuilder = new FlowBuilder();
423         String flowName = FlowNames.getArpResponder(ipAddress);
424         initFlowBuilder(flowBuilder, flowName, getTable(Service.ARP_RESPONDER), FlowID.FLOW_SFARP)
425                 .setPriority(1024);
426
427         MacAddress macAddress = new MacAddress(macAddressStr);
428
429         MatchBuilder matchBuilder = new MatchBuilder();
430         MatchUtils.createInPortReservedMatch(matchBuilder, dataPathId, OutputPortValues.LOCAL.toString());
431         MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(Constants.ARP_ETHERTYPE));
432         MatchUtils.createArpDstIpv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress));
433         flowBuilder.setMatch(matchBuilder.build());
434
435         if (write) {
436             InstructionBuilder ib = new InstructionBuilder();
437             InstructionsBuilder isb = new InstructionsBuilder();
438             List<Instruction> instructions = new ArrayList<>();
439             ApplyActionsBuilder aab = new ApplyActionsBuilder();
440             ActionBuilder ab = new ActionBuilder();
441             List<Action> actionList = new ArrayList<>();
442
443             // Move Eth Src to Eth Dst
444             ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
445             ab.setOrder(0);
446             ab.setKey(new ActionKey(0));
447             actionList.add(ab.build());
448
449             // Set Eth Src
450             ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
451             ab.setOrder(1);
452             ab.setKey(new ActionKey(1));
453             actionList.add(ab.build());
454
455             // Set ARP OP
456             ab.setAction(ActionUtils.nxLoadArpOpAction(BigInteger.valueOf(FlowUtils.ARP_OP_REPLY)));
457             ab.setOrder(2);
458             ab.setKey(new ActionKey(2));
459             actionList.add(ab.build());
460
461             // Move ARP SHA to ARP THA
462             ab.setAction(ActionUtils.nxMoveArpShaToArpThaAction());
463             ab.setOrder(3);
464             ab.setKey(new ActionKey(3));
465             actionList.add(ab.build());
466
467             // Move ARP SPA to ARP TPA
468             ab.setAction(ActionUtils.nxMoveArpSpaToArpTpaAction());
469             ab.setOrder(4);
470             ab.setKey(new ActionKey(4));
471             actionList.add(ab.build());
472
473             // Load Mac to ARP SHA
474             ab.setAction(ActionUtils.nxLoadArpShaAction(macAddress));
475             ab.setOrder(5);
476             ab.setKey(new ActionKey(5));
477             actionList.add(ab.build());
478
479             // Load IP to ARP SPA
480             ab.setAction(ActionUtils.nxLoadArpSpaAction(ipAddress));
481             ab.setOrder(6);
482             ab.setKey(new ActionKey(6));
483             actionList.add(ab.build());
484
485             // Output of InPort
486             ab.setAction(ActionUtils.outputAction(
487                     FlowUtils.getSpecialNodeConnectorId(dataPathId, OutputPortValues.INPORT.toString())));
488             ab.setOrder(7);
489             ab.setKey(new ActionKey(7));
490             actionList.add(ab.build());
491
492             // Create Apply Actions Instruction
493             aab.setAction(actionList);
494             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
495             ib.setOrder(0);
496             ib.setKey(new InstructionKey(0));
497             instructions.add(ib.build());
498
499             isb.setInstruction(instructions);
500             flowBuilder.setInstructions(isb.build());
501             writeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_SFARP);
502         } else {
503             removeFlow(flowBuilder, nodeBuilder, rspName, FlowID.FLOW_SFARP);
504         }
505     }
506
507     private List<Action> getNshAction(NshUtils header, List<Action> actionList) {
508         // Build the Actions to Add the NSH Header
509         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action pushNsh =
510                 ActionUtils.nxPushNshAction();
511         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshMdtypeLoad =
512                 ActionUtils.nxLoadNshMdtypeAction((short) 0x1);
513         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshNpLoad =
514                 ActionUtils.nxLoadNshNpAction((short) 0x3);
515         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
516                 ActionUtils.nxLoadNshc1RegAction(header.getNshMetaC1());
517         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nspLoad =
518                 ActionUtils.nxSetNspAction(header.getNshNsp());
519         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nsiLoad =
520                 ActionUtils.nxSetNsiAction(header.getNshNsi());
521         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid =
522                 ActionUtils.nxLoadTunIdAction(BigInteger.valueOf(header.getNshNsp()), false);
523         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest =
524                 ActionUtils.nxLoadTunIPv4Action(header.getNshTunIpDst().getValue(), false);
525
526         int count = actionList.size();
527         actionList.add(new ActionBuilder()
528                 .setKey(new ActionKey(count)).setOrder(count++).setAction(pushNsh).build());
529         actionList.add(new ActionBuilder()
530                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nshMdtypeLoad).build());
531         actionList.add(new ActionBuilder()
532                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nshNpLoad).build());
533         actionList.add(new ActionBuilder()
534                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nshC1Load).build());
535         actionList.add(new ActionBuilder()
536                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nspLoad).build());
537         actionList.add(new ActionBuilder()
538                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nsiLoad).build());
539         actionList.add(new ActionBuilder()
540                 .setKey(new ActionKey(count)).setOrder(count++).setAction(loadChainTunDest).build());
541         actionList.add(new ActionBuilder()
542                 .setKey(new ActionKey(count)).setOrder(count).setAction(loadChainTunVnid).build());
543         return actionList;
544     }
545
546     private static FlowID flowSet[] = {FlowID.FLOW_INGRESSCLASS, FlowID.FLOW_EGRESSCLASS,
547             FlowID.FLOW_EGRESSCLASSBYPASS, FlowID.FLOW_SFARP, FlowID.FLOW_SFINGRESS, FlowID.FLOW_SFEGRESS};
548
549     @Override
550     public void clearFlows(DataBroker dataBroker, String rspName) {
551         Map<Integer, InstanceIdentifier<Flow>> flowMap = flowCache.getFlows(rspName);
552         if (flowMap != null) {
553             for (FlowID flowID : flowSet) {
554                 InstanceIdentifier<Flow> path = flowMap.get(flowID.value);
555                 if (path != null) {
556                     flowCache.removeFlow(rspName, flowID.value);
557                     removeFlow(dataBroker, path);
558                 }
559             }
560         }
561     }
562
563     private void removeFlow(DataBroker dataBroker, InstanceIdentifier<Flow> path) {
564         WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
565         modification.delete(LogicalDatastoreType.CONFIGURATION, path);
566
567         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
568         try {
569             commitFuture.get();  // TODO: Make it async (See bug 1362)
570             LOG.debug("Transaction success for deletion of Flow {}", path);
571         } catch (Exception e) {
572             LOG.error("Failed to remove flow {}", path, e);
573             modification.cancel();
574         }
575     }
576 }