Merge "Use ClusteredDataTreeListener in hwvtepsb"
[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 UDP_SHORT = 17;
57     static int cookieIndex = 0;
58
59     private enum FlowID {
60         FLOW_INGRESSCLASS(1), FLOW_SFINGRESS(2), FLOW_SFEGRESS(3), FLOW_SFARP(4),
61         FLOW_EGRESSCLASSUNUSED(5), FLOW_EGRESSCLASS(6), FLOW_EGRESSCLASSBYPASS(7), FLOW_SFCTABLE(8);
62
63         private int value;
64         FlowID(int value) {
65             this.value = value;
66         }
67
68     }
69
70     private BigInteger getCookie(FlowID flowID) {
71         String cookieString = String.format("1110%02d%010d", flowID.value, cookieIndex++);
72         return new BigInteger(cookieString, 16);
73     }
74
75     public SfcClassifierService(Service service) {
76         super(service);
77     }
78
79     public SfcClassifierService() {
80         super(Service.SFC_CLASSIFIER);
81     }
82
83     @Override
84     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
85         super.setDependencies(bundleContext.getServiceReference(ISfcClassifierService.class.getName()), this);
86     }
87
88     @Override
89     public void setDependencies(Object impl) {}
90
91     @Override
92     public void programIngressClassifier(long dataPathId, String ruleName, Matches matches,
93                                          NshUtils nshHeader, long vxGpeOfPort, boolean write) {
94         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
95         FlowBuilder flowBuilder = new FlowBuilder();
96
97         MatchBuilder matchBuilder = buildMatch(matches);
98         MatchUtils.addNxRegMatch(matchBuilder,
99                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
100         MatchUtils.addNxRegMatch(matchBuilder,
101                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
102         flowBuilder.setMatch(matchBuilder.build());
103
104         String flowId = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
105         flowBuilder.setId(new FlowId(flowId));
106         FlowKey key = new FlowKey(new FlowId(flowId));
107         flowBuilder.setBarrier(true);
108         flowBuilder.setTableId(getTable());
109         flowBuilder.setKey(key);
110         flowBuilder.setFlowName(flowId);
111         flowBuilder.setHardTimeout(0);
112         flowBuilder.setIdleTimeout(0);
113         flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_INGRESSCLASS)));
114
115         if (write) {
116             ActionBuilder ab = new ActionBuilder();
117             List<Action> actionList = new ArrayList<>();
118
119             ab.setAction(ActionUtils.nxMoveTunIdtoNshc2());
120             ab.setOrder(actionList.size());
121             ab.setKey(new ActionKey(actionList.size()));
122             actionList.add(ab.build());
123
124             getNshAction(nshHeader, actionList);
125
126             ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(dataPathId, vxGpeOfPort)));
127             ab.setOrder(actionList.size());
128             ab.setKey(new ActionKey(actionList.size()));
129             actionList.add(ab.build());
130
131             ApplyActionsBuilder aab = new ApplyActionsBuilder();
132             aab.setAction(actionList);
133
134             InstructionBuilder ib = new InstructionBuilder();
135             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
136             ib.setOrder(0);
137             ib.setKey(new InstructionKey(0));
138             List<Instruction> instructions = Lists.newArrayList();
139             instructions.add(ib.build());
140
141             InstructionsBuilder isb = new InstructionsBuilder();
142             isb.setInstruction(instructions);
143             flowBuilder.setInstructions(isb.build());
144             writeFlow(flowBuilder, nodeBuilder);
145         } else {
146             removeFlow(flowBuilder, nodeBuilder);
147         }
148     }
149
150     @Override
151     public void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write) {
152         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
153         FlowBuilder flowBuilder = new FlowBuilder();
154
155         MatchBuilder matchBuilder = new MatchBuilder();
156         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
157         flowBuilder.setMatch(matchBuilder.build());
158
159         String flowId = "sfcTable_" + vxGpeOfPort;
160         flowBuilder.setId(new FlowId(flowId));
161         FlowKey key = new FlowKey(new FlowId(flowId));
162         flowBuilder.setBarrier(true);
163         flowBuilder.setTableId(getTable(Service.CLASSIFIER));
164         flowBuilder.setKey(key);
165         flowBuilder.setFlowName(flowId);
166         flowBuilder.setHardTimeout(0);
167         flowBuilder.setIdleTimeout(0);
168         flowBuilder.setPriority(1000);
169         flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
170         flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
171
172         if (write) {
173             InstructionsBuilder isb = new InstructionsBuilder();
174             List<Instruction> instructions = Lists.newArrayList();
175             InstructionBuilder ib =
176                     InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), goToTableId);
177             ib.setOrder(0);
178             ib.setKey(new InstructionKey(0));
179             instructions.add(ib.build());
180
181             isb.setInstruction(instructions);
182             flowBuilder.setInstructions(isb.build());
183             writeFlow(flowBuilder, nodeBuilder);
184         } else {
185             removeFlow(flowBuilder, nodeBuilder);
186         }
187     }
188
189     @Override
190     public void programEgressClassifier1(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
191                                          int tunnelOfPort, int tunnelId, short gotoTableId, boolean write) {
192         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
193         FlowBuilder flowBuilder = new FlowBuilder();
194
195         MatchBuilder matchBuilder = new MatchBuilder();
196         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
197         MatchUtils.addNxNspMatch(matchBuilder, nsp);
198         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
199         flowBuilder.setMatch(matchBuilder.build());
200
201         String flowId = "sfcEgressClass1_" + vxGpeOfPort;
202         flowBuilder.setId(new FlowId(flowId));
203         FlowKey key = new FlowKey(new FlowId(flowId));
204         flowBuilder.setBarrier(true);
205         flowBuilder.setTableId(getTable(Service.CLASSIFIER));
206         flowBuilder.setKey(key);
207         flowBuilder.setFlowName(flowId);
208         flowBuilder.setHardTimeout(0);
209         flowBuilder.setIdleTimeout(0);
210         flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
211         flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
212
213         if (write) {
214             InstructionsBuilder isb = new InstructionsBuilder();
215             List<Instruction> instructions = Lists.newArrayList();
216
217             InstructionBuilder ib = InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), getTable());
218             ib.setOrder(instructions.size());
219             ib.setKey(new InstructionKey(instructions.size()));
220             instructions.add(ib.build());
221
222             isb.setInstruction(instructions);
223             flowBuilder.setInstructions(isb.build());
224             writeFlow(flowBuilder, nodeBuilder);
225         } else {
226             removeFlow(flowBuilder, nodeBuilder);
227         }
228     }
229
230     @Override
231     public void programEgressClassifier(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
232                                         long sfOfPort, int tunnelId, boolean write) {
233         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
234         FlowBuilder flowBuilder = new FlowBuilder();
235
236         MatchBuilder matchBuilder = new MatchBuilder();
237         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
238         MatchUtils.addNxNspMatch(matchBuilder, nsp);
239         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
240         flowBuilder.setMatch(matchBuilder.build());
241
242         String flowId = "sfcEgressClass_" + nsp + "_" + + nsi + "_"  + vxGpeOfPort;
243         flowBuilder.setId(new FlowId(flowId));
244         FlowKey key = new FlowKey(new FlowId(flowId));
245         flowBuilder.setBarrier(true);
246         flowBuilder.setTableId(getTable(Service.CLASSIFIER));
247         flowBuilder.setKey(key);
248         flowBuilder.setFlowName(flowId);
249         flowBuilder.setHardTimeout(0);
250         flowBuilder.setIdleTimeout(0);
251         flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
252         flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
253
254         if (write) {
255             InstructionsBuilder isb = new InstructionsBuilder();
256             List<Instruction> instructions = Lists.newArrayList();
257             List<Action> actionList = Lists.newArrayList();
258
259             ActionBuilder ab = new ActionBuilder();
260
261             ab.setAction(
262                     ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(FlowUtils.REG_FIELD).build(),
263                     BigInteger.valueOf(FlowUtils.REG_VALUE_FROM_LOCAL)));
264             ab.setOrder(actionList.size());
265             ab.setKey(new ActionKey(actionList.size()));
266             actionList.add(ab.build());
267
268             ab.setAction(ActionUtils.nxMoveNshc2ToTunId());
269             ab.setOrder(actionList.size());
270             ab.setKey(new ActionKey(actionList.size()));
271             actionList.add(ab.build());
272
273             ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, Service.CLASSIFIER.getTable()));
274             ab.setOrder(actionList.size());
275             ab.setKey(new ActionKey(actionList.size()));
276             actionList.add(ab.build());
277
278             ApplyActionsBuilder aab = new ApplyActionsBuilder();
279             aab.setAction(actionList);
280             InstructionBuilder ib = new InstructionBuilder();
281             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
282
283             ib.setOrder(0);
284             ib.setKey(new InstructionKey(0));
285             instructions.add(ib.build());
286
287             isb.setInstruction(instructions);
288             flowBuilder.setInstructions(isb.build());
289             writeFlow(flowBuilder, nodeBuilder);
290         } else {
291             removeFlow(flowBuilder, nodeBuilder);
292         }
293     }
294
295     private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID) {
296         FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
297                 .setCookie(new FlowCookie(getCookie(flowID)))
298                 .setCookieMask(new FlowCookie(getCookie(flowID)));
299         return flowBuilder;
300     }
301
302     @Override
303     public void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
304                                               long sfOfPort, int tunnelId, boolean write) {
305         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
306         FlowBuilder flowBuilder = new FlowBuilder();
307         String flowName = "sfcEgressClassBypass_" + nsp + "_" + + nsi + "_"  + sfOfPort;
308         initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(),
309                 FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000);
310
311         MatchBuilder matchBuilder = new MatchBuilder();
312         MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort);
313         MatchUtils.addNxRegMatch(matchBuilder,
314                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
315         MatchUtils.addNxNspMatch(matchBuilder, nsp);
316         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
317         flowBuilder.setMatch(matchBuilder.build());
318
319         if (write) {
320             InstructionsBuilder isb = new InstructionsBuilder();
321             List<Instruction> instructions = Lists.newArrayList();
322
323             InstructionBuilder ib;
324             ib = this.getMutablePipelineInstructionBuilder();
325             ib.setOrder(0);
326             ib.setKey(new InstructionKey(0));
327             instructions.add(ib.build());
328
329             isb.setInstruction(instructions);
330             flowBuilder.setInstructions(isb.build());
331             writeFlow(flowBuilder, nodeBuilder);
332         } else {
333             removeFlow(flowBuilder, nodeBuilder);
334         }
335     }
336
337     // packet from sf to sff that need to go out local
338     @Override
339     public void program_sfEgress(long dataPathId, int dstPort, boolean write) {
340         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
341         FlowBuilder flowBuilder = new FlowBuilder();
342         String flowName = "sfEgress_" + dstPort;
343         initFlowBuilder(flowBuilder, flowName, getTable(), FlowID.FLOW_SFEGRESS);
344
345         MatchBuilder matchBuilder = new MatchBuilder();
346         MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
347         MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
348         MatchUtils.addNxRegMatch(matchBuilder,
349                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
350         flowBuilder.setMatch(matchBuilder.build());
351
352         if (write) {
353             InstructionBuilder ib = new InstructionBuilder();
354             InstructionsBuilder isb = new InstructionsBuilder();
355             List<Instruction> instructions = Lists.newArrayList();
356             InstructionUtils.createLocalInstructions(ib, dataPathId);
357             ib.setOrder(0);
358             ib.setKey(new InstructionKey(0));
359             instructions.add(ib.build());
360
361             isb.setInstruction(instructions);
362             flowBuilder.setInstructions(isb.build());
363             writeFlow(flowBuilder, nodeBuilder);
364         } else {
365             removeFlow(flowBuilder, nodeBuilder);
366         }
367     }
368
369     // looped back sff to sf packets
370     @Override
371     public void program_sfIngress(long dataPathId, int dstPort, long sfOfPort,
372                                   String ipAddress, String sfDplName, boolean write) {
373         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
374         FlowBuilder flowBuilder = new FlowBuilder();
375         String flowName = "sfIngress_" + dstPort + "_" + ipAddress;
376         initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFINGRESS);
377
378         MatchBuilder matchBuilder = new MatchBuilder();
379         MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
380         Ipv4Prefix ipCidr = MatchUtils.iPv4PrefixFromIPv4Address(ipAddress);
381         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(ipCidr));
382         MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
383         flowBuilder.setMatch(matchBuilder.build());
384
385         if (write) {
386             InstructionBuilder ib = new InstructionBuilder();
387             InstructionsBuilder isb = new InstructionsBuilder();
388             List<Instruction> instructions = Lists.newArrayList();
389             InstructionUtils.createOutputPortInstructions(ib, dataPathId, sfOfPort);
390
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     @Override
404     public void programStaticArpEntry(long dataPathId, long ofPort, String macAddressStr,
405                                       String ipAddress, boolean write) {
406         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
407         FlowBuilder flowBuilder = new FlowBuilder();
408         String flowName = "ArpResponder_" + ipAddress;
409         initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFARP).setPriority(1024);
410
411         MacAddress macAddress = new MacAddress(macAddressStr);
412
413         MatchBuilder matchBuilder = new MatchBuilder();
414         MatchUtils.createInPortReservedMatch(matchBuilder, dataPathId, OutputPortValues.LOCAL.toString());
415         MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(Constants.ARP_ETHERTYPE));
416         MatchUtils.createArpDstIpv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress));
417         flowBuilder.setMatch(matchBuilder.build());
418
419         if (write) {
420             InstructionBuilder ib = new InstructionBuilder();
421             InstructionsBuilder isb = new InstructionsBuilder();
422             List<Instruction> instructions = Lists.newArrayList();
423             ApplyActionsBuilder aab = new ApplyActionsBuilder();
424             ActionBuilder ab = new ActionBuilder();
425             List<Action> actionList = Lists.newArrayList();
426
427             // Move Eth Src to Eth Dst
428             ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
429             ab.setOrder(0);
430             ab.setKey(new ActionKey(0));
431             actionList.add(ab.build());
432
433             // Set Eth Src
434             ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
435             ab.setOrder(1);
436             ab.setKey(new ActionKey(1));
437             actionList.add(ab.build());
438
439             // Set ARP OP
440             ab.setAction(ActionUtils.nxLoadArpOpAction(BigInteger.valueOf(FlowUtils.ARP_OP_REPLY)));
441             ab.setOrder(2);
442             ab.setKey(new ActionKey(2));
443             actionList.add(ab.build());
444
445             // Move ARP SHA to ARP THA
446             ab.setAction(ActionUtils.nxMoveArpShaToArpThaAction());
447             ab.setOrder(3);
448             ab.setKey(new ActionKey(3));
449             actionList.add(ab.build());
450
451             // Move ARP SPA to ARP TPA
452             ab.setAction(ActionUtils.nxMoveArpSpaToArpTpaAction());
453             ab.setOrder(4);
454             ab.setKey(new ActionKey(4));
455             actionList.add(ab.build());
456
457             // Load Mac to ARP SHA
458             ab.setAction(ActionUtils.nxLoadArpShaAction(macAddress));
459             ab.setOrder(5);
460             ab.setKey(new ActionKey(5));
461             actionList.add(ab.build());
462
463             // Load IP to ARP SPA
464             ab.setAction(ActionUtils.nxLoadArpSpaAction(ipAddress));
465             ab.setOrder(6);
466             ab.setKey(new ActionKey(6));
467             actionList.add(ab.build());
468
469             // Output of InPort
470             ab.setAction(ActionUtils.outputAction(
471                     FlowUtils.getSpecialNodeConnectorId(dataPathId, OutputPortValues.INPORT.toString())));
472             ab.setOrder(7);
473             ab.setKey(new ActionKey(7));
474             actionList.add(ab.build());
475
476             // Create Apply Actions Instruction
477             aab.setAction(actionList);
478             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
479             ib.setOrder(0);
480             ib.setKey(new InstructionKey(0));
481             instructions.add(ib.build());
482
483             isb.setInstruction(instructions);
484             flowBuilder.setInstructions(isb.build());
485             writeFlow(flowBuilder, nodeBuilder);
486         } else {
487             removeFlow(flowBuilder, nodeBuilder);
488         }
489     }
490
491     private List<Action> getNshAction(NshUtils header, List<Action> actionList) {
492         // Build the Actions to Add the NSH Header
493         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
494                 ActionUtils.nxLoadNshc1RegAction(header.getNshMetaC1());
495         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nspLoad =
496                 ActionUtils.nxSetNspAction(header.getNshNsp());
497         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nsiLoad =
498                 ActionUtils.nxSetNsiAction(header.getNshNsi());
499         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid =
500                 ActionUtils.nxLoadTunIdAction(BigInteger.valueOf(header.getNshNsp()), false);
501         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest =
502                 ActionUtils.nxLoadTunIPv4Action(header.getNshTunIpDst().getValue(), false);
503
504         int count = actionList.size();
505         actionList.add(new ActionBuilder()
506                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nshC1Load).build());
507         actionList.add(new ActionBuilder()
508                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nspLoad).build());
509         actionList.add(new ActionBuilder()
510                 .setKey(new ActionKey(count)).setOrder(count++).setAction(nsiLoad).build());
511         actionList.add(new ActionBuilder()
512                 .setKey(new ActionKey(count)).setOrder(count++).setAction(loadChainTunDest).build());
513         actionList.add(new ActionBuilder()
514                 .setKey(new ActionKey(count)).setOrder(count).setAction(loadChainTunVnid).build());
515         return actionList;
516     }
517
518     public MatchBuilder buildMatch(Matches matches) {
519         MatchBuilder matchBuilder = new MatchBuilder();
520
521         if (matches.getAceType() instanceof AceIp) {
522             AceIp aceIp = (AceIp)matches.getAceType();
523             if (aceIp.getAceIpVersion() instanceof AceIpv4) {
524                 MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
525                 MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
526                         aceIp.getDestinationPortRange().getLowerPort().getValue());
527             } else {
528                 MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
529                 MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
530                         aceIp.getDestinationPortRange().getLowerPort().getValue());
531             }
532         } else if (matches.getAceType() instanceof AceEth) {
533             AceEth aceEth = (AceEth) matches.getAceType();
534             MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(aceEth.getSourceMacAddress().getValue()));
535             MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(aceEth.getDestinationMacAddress().getValue()),
536                     new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
537         }
538
539         LOG.info("buildMatch: {}", matchBuilder.build());
540         return matchBuilder;
541     }
542 }