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