Bug 7725: AAP with prefix 0.0.0.0/0 not supported in ACL
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / listeners / AclNodeListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.aclservice.listeners;
10
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
14 import javax.annotation.PostConstruct;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
20 import org.opendaylight.genius.mdsalutil.ActionInfo;
21 import org.opendaylight.genius.mdsalutil.FlowEntity;
22 import org.opendaylight.genius.mdsalutil.InstructionInfo;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.MatchInfo;
25 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
26 import org.opendaylight.genius.mdsalutil.NwConstants;
27 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
28 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
29 import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
30 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
31 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
32 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
33 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
34 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
35 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
36 import org.opendaylight.genius.mdsalutil.matches.MatchTcpFlags;
37 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
38 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig.SecurityGroupMode;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 /**
50  * Listener to handle flow capable node updates.
51  */
52 @Singleton
53 @SuppressWarnings("deprecation")
54 public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapableNode, AclNodeListener>
55         implements AutoCloseable {
56
57     private static final Logger LOG = LoggerFactory.getLogger(AclNodeListener.class);
58
59     private final IMdsalApiManager mdsalManager;
60     private final AclserviceConfig config;
61     private final DataBroker dataBroker;
62     private final AclServiceUtils aclServiceUtils;
63
64     private SecurityGroupMode securityGroupMode = null;
65
66     @Inject
67     public AclNodeListener(final IMdsalApiManager mdsalManager, DataBroker dataBroker, AclserviceConfig config,
68             AclServiceUtils aclServiceUtils) {
69         super(FlowCapableNode.class, AclNodeListener.class);
70
71         this.mdsalManager = mdsalManager;
72         this.dataBroker = dataBroker;
73         this.config = config;
74         this.aclServiceUtils = aclServiceUtils;
75     }
76
77     @Override
78     @PostConstruct
79     public void init() {
80         LOG.info("{} start", getClass().getSimpleName());
81         if (config != null) {
82             this.securityGroupMode = config.getSecurityGroupMode();
83         }
84         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
85         LOG.info("AclserviceConfig: {}", this.config);
86     }
87
88     @Override
89     protected InstanceIdentifier<FlowCapableNode> getWildCardPath() {
90         return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
91     }
92
93     @Override
94     protected void remove(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
95         NodeKey nodeKey = key.firstKeyOf(Node.class);
96         BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
97         this.aclServiceUtils.deleteAclIdPools(dpnId);
98     }
99
100     @Override
101     protected void update(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModificationBefore,
102             FlowCapableNode dataObjectModificationAfter) {
103         // do nothing
104     }
105
106     @Override
107     protected void add(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
108         LOG.trace("FlowCapableNode Added: key: {}", key);
109         NodeKey nodeKey = key.firstKeyOf(Node.class);
110         BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
111         createTableDefaultEntries(dpnId);
112
113         this.aclServiceUtils.createAclIdPools(dpnId);
114     }
115
116     /**
117      * Creates the table miss entries.
118      *
119      * @param dpnId the dpn id
120      */
121     private void createTableDefaultEntries(BigInteger dpnId) {
122         LOG.info("Adding default ACL entries for mode: "
123                 + (securityGroupMode == null ? SecurityGroupMode.Stateful : securityGroupMode));
124         if (securityGroupMode == null || securityGroupMode == SecurityGroupMode.Stateful) {
125             addIngressAclTableMissFlow(dpnId);
126             addEgressAclTableMissFlow(dpnId);
127             addConntrackRules(dpnId, NwConstants.LPORT_DISPATCHER_TABLE, NwConstants.INGRESS_ACL_FILTER_TABLE,
128                     NwConstants.ADD_FLOW);
129             addConntrackRules(dpnId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, NwConstants.EGRESS_ACL_FILTER_TABLE,
130                     NwConstants.ADD_FLOW);
131         } else if (securityGroupMode == SecurityGroupMode.Transparent) {
132             addTransparentIngressAclTableMissFlow(dpnId);
133             addTransparentEgressAclTableMissFlow(dpnId);
134         } else if (securityGroupMode == SecurityGroupMode.Stateless) {
135             addStatelessIngressAclTableMissFlow(dpnId);
136             addStatelessEgressAclTableMissFlow(dpnId);
137         } else if (securityGroupMode == SecurityGroupMode.Learn) {
138             addLearnIngressAclTableMissFlow(dpnId);
139             addLearnEgressAclTableMissFlow(dpnId);
140         }
141     }
142
143     /**
144      * Adds the ingress acl table miss flow.
145      *
146      * @param dpId the dp id
147      */
148     private void addIngressAclTableMissFlow(BigInteger dpId) {
149         List<MatchInfo> mkMatches = new ArrayList<>();
150         List<InstructionInfo> mkInstructions = new ArrayList<>();
151         List<ActionInfo> actionsInfos = new ArrayList<>();
152         actionsInfos.add(new ActionDrop());
153         mkInstructions.add(new InstructionApplyActions(actionsInfos));
154
155         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
156                 getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Ingress ACL Table Miss Flow", 0, 0,
157                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
158         mdsalManager.installFlow(flowEntity);
159
160         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
161                 getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0, "Ingress ACL Filter Table Miss Flow",
162                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
163         mdsalManager.installFlow(nextTblFlowEntity);
164
165         LOG.debug("Added Ingress ACL Table Miss Flows for dpn {}", dpId);
166     }
167
168     private void addLearnEgressAclTableMissFlow(BigInteger dpId) {
169         List<InstructionInfo> mkInstructions = new ArrayList<>();
170         List<ActionInfo> actionsInfos = new ArrayList<>();
171         actionsInfos.add(new ActionNxResubmit(NwConstants.EGRESS_LEARN_TABLE));
172         actionsInfos.add(new ActionNxResubmit(NwConstants.EGRESS_LEARN2_TABLE));
173         mkInstructions.add(new InstructionApplyActions(actionsInfos));
174
175         List<MatchInfo> mkMatches = new ArrayList<>();
176         FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
177                 "RESUB-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
178                 AclConstants.PROTO_MATCH_PRIORITY, "Egress resubmit ACL Table Block", 0, 0,
179                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
180         mdsalManager.installFlow(doubleResubmitTable);
181
182         mkMatches = new ArrayList<>();
183         mkInstructions = new ArrayList<>();
184         actionsInfos = new ArrayList<>();
185         actionsInfos.add(new ActionDrop());
186         mkInstructions.add(new InstructionApplyActions(actionsInfos));
187
188         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN2_TABLE,
189                 "LEARN-" + getTableMissFlowId(NwConstants.EGRESS_LEARN2_TABLE), 0,
190                 "Egress Learn2 ACL Table Miss Flow", 0, 0,
191                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
192         mdsalManager.installFlow(flowEntity);
193
194         List<NxMatchInfo> nxMkMatches = new ArrayList<>();
195         nxMkMatches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_5,
196                 new long[] {Long.valueOf(AclConstants.LEARN_MATCH_REG_VALUE)}));
197
198         short dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
199         List<InstructionInfo> instructions = new ArrayList<>();
200         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
201         instructions.add(new InstructionApplyActions(actionsInfos));
202
203         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN2_TABLE,
204                 "LEARN2-REG-" + getTableMissFlowId(NwConstants.EGRESS_LEARN2_TABLE),
205                 AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
206                 AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
207         mdsalManager.installFlow(flowEntity);
208         LOG.debug("Added learn ACL Table Miss Flows for dpn {}", dpId);
209     }
210
211     private void addLearnIngressAclTableMissFlow(BigInteger dpId) {
212         List<InstructionInfo> mkInstructions = new ArrayList<>();
213         List<ActionInfo> actionsInfos = new ArrayList<>();
214         actionsInfos.add(new ActionNxResubmit(NwConstants.INGRESS_LEARN_TABLE));
215         actionsInfos.add(new ActionNxResubmit(NwConstants.INGRESS_LEARN2_TABLE));
216         mkInstructions.add(new InstructionApplyActions(actionsInfos));
217
218         List<MatchInfo> mkMatches = new ArrayList<>();
219         FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
220                 "RESUB-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
221                 AclConstants.PROTO_MATCH_PRIORITY, "Ingress resubmit ACL Table Block", 0, 0,
222                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
223         mdsalManager.installFlow(doubleResubmitTable);
224
225         mkMatches = new ArrayList<>();
226         mkInstructions = new ArrayList<>();
227         actionsInfos = new ArrayList<>();
228         actionsInfos.add(new ActionDrop());
229         mkInstructions.add(new InstructionApplyActions(actionsInfos));
230
231         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN2_TABLE,
232                 "LEARN-" + getTableMissFlowId(NwConstants.INGRESS_LEARN2_TABLE), 0,
233                 "Ingress Learn2 ACL Table Miss Flow", 0, 0,
234                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
235         mdsalManager.installFlow(flowEntity);
236
237         List<NxMatchInfo> nxMkMatches = new ArrayList<>();
238         nxMkMatches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_5,
239                 new long[] {Long.valueOf(AclConstants.LEARN_MATCH_REG_VALUE)}));
240
241         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
242         List<InstructionInfo> instructions = new ArrayList<>();
243         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
244         instructions.add(new InstructionApplyActions(actionsInfos));
245
246         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN2_TABLE,
247                 "LEARN2-REG-" + getTableMissFlowId(NwConstants.INGRESS_LEARN2_TABLE),
248                 AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
249                 AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
250         mdsalManager.installFlow(flowEntity);
251         LOG.debug("Added learn ACL Table Miss Flows for dpn {}", dpId);
252
253     }
254
255     /**
256      * Adds the ingress acl table transparent flow.
257      *
258      * @param dpId the dp id
259      */
260     private void addTransparentIngressAclTableMissFlow(BigInteger dpId) {
261         List<MatchInfo> mkMatches = new ArrayList<>();
262         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
263         allowAllInstructions.add(new InstructionGotoTable(NwConstants.INGRESS_ACL_FILTER_TABLE));
264
265         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
266                 getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Ingress ACL Table allow all Flow",
267                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
268         mdsalManager.installFlow(nextTblFlowEntity);
269
270         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
271
272         List<ActionInfo> actionsInfos = new ArrayList<>();
273         List<InstructionInfo> dispatcherInstructions = new ArrayList<>();
274         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
275         dispatcherInstructions.add(new InstructionApplyActions(actionsInfos));
276
277         nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
278                 getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0, "Ingress ACL Filter Table allow all Flow",
279                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, dispatcherInstructions);
280         mdsalManager.installFlow(nextTblFlowEntity);
281
282         LOG.debug("Added Transparent Ingress ACL Table allow all Flows for dpn {}", dpId);
283     }
284
285     /**
286      * Adds the egress acl table transparent flow.
287      *
288      * @param dpId the dp id
289      */
290     private void addTransparentEgressAclTableMissFlow(BigInteger dpId) {
291         List<MatchInfo> mkMatches = new ArrayList<>();
292         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
293         allowAllInstructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_FILTER_TABLE));
294
295         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
296                 getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Egress ACL Table allow all Flow",
297                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
298         mdsalManager.installFlow(nextTblFlowEntity);
299
300         short dispatcherTableId =  NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
301
302         List<ActionInfo> actionsInfos = new ArrayList<>();
303         List<InstructionInfo> instructions = new ArrayList<>();
304         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
305         instructions.add(new InstructionApplyActions(actionsInfos));
306
307         nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
308                 getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0, "Egress ACL Filter Table allow all Flow",
309                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, instructions);
310         mdsalManager.installFlow(nextTblFlowEntity);
311
312         LOG.debug("Added Transparent Egress ACL Table allow all Flows for dpn {}", dpId);
313     }
314
315     /**
316      * Adds the ingress acl table miss flow.
317      *
318      * @param dpId the dp id
319      */
320     private void addStatelessIngressAclTableMissFlow(BigInteger dpId) {
321         List<MatchInfo> synMatches = new ArrayList<>();
322         synMatches.add(MatchEthernetType.IPV4);
323         synMatches.add(MatchIpProtocol.TCP);
324
325         synMatches.add(MatchTcpFlags.SYN);
326
327         List<ActionInfo> dropActionsInfos = new ArrayList<>();
328         dropActionsInfos.add(new ActionDrop());
329         List<InstructionInfo> synInstructions = new ArrayList<>();
330         synInstructions.add(new InstructionApplyActions(dropActionsInfos));
331
332         FlowEntity synFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
333                 "SYN-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
334                 AclConstants.PROTO_MATCH_SYN_DROP_PRIORITY, "Ingress Syn ACL Table Block", 0, 0,
335                 AclConstants.COOKIE_ACL_BASE, synMatches, synInstructions);
336         mdsalManager.installFlow(synFlowEntity);
337
338         synMatches = new ArrayList<>();
339         synMatches.add(MatchEthernetType.IPV4);
340         synMatches.add(MatchIpProtocol.TCP);
341         synMatches.add(MatchTcpFlags.SYN_ACK);
342
343         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
344         allowAllInstructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_FILTER_TABLE));
345
346         FlowEntity synAckFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
347                 "SYN-ACK-ALLOW-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
348                 AclConstants.PROTO_MATCH_SYN_ACK_ALLOW_PRIORITY, "Ingress Syn Ack ACL Table Allow", 0, 0,
349                 AclConstants.COOKIE_ACL_BASE, synMatches, allowAllInstructions);
350         mdsalManager.installFlow(synAckFlowEntity);
351
352
353         List<MatchInfo> mkMatches = new ArrayList<>();
354         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
355                 getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Ingress Stateless ACL Table Miss Flow",
356                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
357         mdsalManager.installFlow(flowEntity);
358
359         short dispatcherTableId =  NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
360
361         List<ActionInfo> actionsInfos = new ArrayList<>();
362         List<InstructionInfo> instructions = new ArrayList<>();
363         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
364         instructions.add(new InstructionApplyActions(actionsInfos));
365
366         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
367                 getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0,
368                 "Ingress Stateless Next ACL Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE,
369                 mkMatches, instructions);
370         mdsalManager.installFlow(nextTblFlowEntity);
371
372         LOG.debug("Added Stateless Ingress ACL Table Miss Flows for dpn {}.", dpId);
373     }
374
375     /**
376      * Adds the stateless egress acl table miss flow.
377      *
378      * @param dpId the dp id
379      */
380     private void addStatelessEgressAclTableMissFlow(BigInteger dpId) {
381         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
382         allowAllInstructions.add(new InstructionGotoTable(NwConstants.INGRESS_ACL_FILTER_TABLE));
383
384         List<MatchInfo> synMatches = new ArrayList<>();
385         synMatches.add(MatchEthernetType.IPV4);
386         synMatches.add(MatchIpProtocol.TCP);
387         synMatches.add(MatchTcpFlags.SYN);
388
389         List<ActionInfo> synActionsInfos = new ArrayList<>();
390         synActionsInfos.add(new ActionDrop());
391         List<InstructionInfo> synInstructions = new ArrayList<>();
392         synInstructions.add(new InstructionApplyActions(synActionsInfos));
393
394         FlowEntity synFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
395                 "SYN-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
396                 AclConstants.PROTO_MATCH_SYN_DROP_PRIORITY, "Egress Syn ACL Table Block", 0, 0,
397                 AclConstants.COOKIE_ACL_BASE, synMatches, synInstructions);
398         mdsalManager.installFlow(synFlowEntity);
399
400         synMatches = new ArrayList<>();
401         synMatches.add(MatchEthernetType.IPV4);
402         synMatches.add(MatchIpProtocol.TCP);
403         synMatches.add(MatchTcpFlags.SYN_ACK);
404
405         FlowEntity synAckFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
406                 "SYN-ACK-ALLOW-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
407                 AclConstants.PROTO_MATCH_SYN_ACK_ALLOW_PRIORITY, "Egress Syn Ack ACL Table Allow", 0, 0,
408                 AclConstants.COOKIE_ACL_BASE, synMatches, allowAllInstructions);
409         mdsalManager.installFlow(synAckFlowEntity);
410
411         List<MatchInfo> mkMatches = new ArrayList<>();
412         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
413                 getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Egress Stateless ACL Table Miss Flow", 0, 0,
414                 AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
415         mdsalManager.installFlow(flowEntity);
416
417         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
418
419         List<ActionInfo> actionsInfos = new ArrayList<>();
420         List<InstructionInfo> dispatcherInstructions = new ArrayList<>();
421         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
422         dispatcherInstructions.add(new InstructionApplyActions(actionsInfos));
423
424         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
425                 getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0,
426                 "Egress Stateless Next ACL Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches,
427                 dispatcherInstructions);
428         mdsalManager.installFlow(nextTblFlowEntity);
429
430         LOG.debug("Added Stateless Egress ACL Table Miss Flows for dpn {}", dpId);
431     }
432
433     /**
434      * Adds the egress acl table miss flow.
435      *
436      * @param dpId the dp id
437      */
438     private void addEgressAclTableMissFlow(BigInteger dpId) {
439         List<MatchInfo> mkMatches = new ArrayList<>();
440         List<InstructionInfo> mkInstructions = new ArrayList<>();
441         List<ActionInfo> actionsInfos = new ArrayList<>();
442         actionsInfos.add(new ActionDrop());
443         mkInstructions.add(new InstructionApplyActions(actionsInfos));
444
445         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
446                 getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Egress ACL Table Miss Flow", 0, 0,
447                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
448         mdsalManager.installFlow(flowEntity);
449
450         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
451                 getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0, "Egress ACL Table Miss Flow", 0, 0,
452                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
453         mdsalManager.installFlow(nextTblFlowEntity);
454
455         LOG.debug("Added Egress ACL Table Miss Flows for dpn {}", dpId);
456     }
457
458     private void addConntrackRules(BigInteger dpnId, short dispatcherTableId,short tableId, int write) {
459         programConntrackForwardRule(dpnId, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,
460             "Tracked_Established", AclConstants.TRACKED_EST_CT_STATE, AclConstants.TRACKED_EST_CT_STATE_MASK,
461             dispatcherTableId, tableId, write);
462         programConntrackForwardRule(dpnId, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,"Tracked_Related", AclConstants
463             .TRACKED_REL_CT_STATE, AclConstants.TRACKED_REL_CT_STATE_MASK, dispatcherTableId, tableId, write);
464     }
465
466     /**
467      * Adds the rule to forward the packets known packets.
468      *
469      * @param dpId the dpId
470      * @param priority the priority of the flow
471      * @param flowId the flowId
472      * @param conntrackState the conntrack state of the packets thats should be
473      *        send
474      * @param conntrackMask the conntrack mask
475      * @param dispatcherTableId the dispatcher table id
476      * @param tableId the table id
477      * @param addOrRemove whether to add or remove the flow
478      */
479     private void programConntrackForwardRule(BigInteger dpId, Integer priority, String flowId,
480             int conntrackState, int conntrackMask, short dispatcherTableId, short tableId, int addOrRemove) {
481         List<MatchInfoBase> matches = new ArrayList<>();
482         matches.add(new NxMatchInfo(NxMatchFieldType.ct_state, new long[] {conntrackState, conntrackMask}));
483
484         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(
485             new ArrayList<>(),dispatcherTableId);
486
487         flowId = "Fixed_Conntrk_Trk_" + dpId + "_" + flowId + dispatcherTableId;
488         syncFlow(dpId, tableId, flowId, priority, "ACL", 0, 0,
489                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
490     }
491
492     /**
493      * Gets the dispatcher table resubmit instructions.
494      *
495      * @param actionsInfos the actions infos
496      * @param dispatcherTableId the dispatcher table id
497      * @return the instructions for dispatcher table resubmit
498      */
499     private List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos,
500                                                                          short dispatcherTableId) {
501         List<InstructionInfo> instructions = new ArrayList<>();
502         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
503         instructions.add(new InstructionApplyActions(actionsInfos));
504         return instructions;
505     }
506
507     /**
508      * Writes/remove the flow to/from the datastore.
509      * @param dpId the dpId
510      * @param tableId the tableId
511      * @param flowId the flowId
512      * @param priority the priority
513      * @param flowName the flow name
514      * @param idleTimeOut the idle timeout
515      * @param hardTimeOut the hard timeout
516      * @param cookie the cookie
517      * @param matches the list of matches to be written
518      * @param instructions the list of instruction to be written.
519      * @param addOrRemove add or remove the entries.
520      */
521     protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
522                           int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase>  matches,
523                           List<InstructionInfo> instructions, int addOrRemove) {
524         if (addOrRemove == NwConstants.DEL_FLOW) {
525             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,flowId,
526                 priority, flowName , idleTimeOut, hardTimeOut, cookie, matches, null);
527             LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
528             mdsalManager.removeFlow(flowEntity);
529         } else {
530             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId,
531                 priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions);
532             LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
533             mdsalManager.installFlow(flowEntity);
534         }
535     }
536
537     /**
538      * Gets the table miss flow id.
539      *
540      * @param tableId the table id
541      * @return the table miss flow id
542      */
543     private String getTableMissFlowId(short tableId) {
544         return String.valueOf(tableId);
545     }
546
547     @Override
548     protected AclNodeListener getDataTreeChangeListener() {
549         return AclNodeListener.this;
550     }
551 }