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