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