Merge "Copy default aclservice-config.xml to etc/...config"
[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
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
18 import org.opendaylight.genius.mdsalutil.ActionInfo;
19 import org.opendaylight.genius.mdsalutil.ActionType;
20 import org.opendaylight.genius.mdsalutil.FlowEntity;
21 import org.opendaylight.genius.mdsalutil.InstructionInfo;
22 import org.opendaylight.genius.mdsalutil.InstructionType;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.MatchFieldType;
25 import org.opendaylight.genius.mdsalutil.MatchInfo;
26 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
29 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
30 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
31 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
32 import org.opendaylight.netvirt.aclservice.utils.AclClusterUtil;
33 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig.SecurityGroupMode;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44
45
46 /**
47  * Listener to handle flow capable node updates.
48  */
49 @SuppressWarnings("deprecation")
50 public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapableNode, AclNodeListener>
51         implements AutoCloseable {
52
53     /** The Constant LOG. */
54     private static final Logger LOG = LoggerFactory.getLogger(AclNodeListener.class);
55
56     /** The mdsal manager. */
57     private final IMdsalApiManager mdsalManager;
58
59     /** The data broker. */
60     private final DataBroker dataBroker;
61
62     private SecurityGroupMode securityGroupMode = null;
63
64     private AclserviceConfig config;
65
66     /**
67      * Instantiates a new acl node listener.
68      *
69      * @param mdsalManager the mdsal manager
70      * @param dataBroker the data broker
71      * @param config aclservice configuration
72      */
73     public AclNodeListener(final IMdsalApiManager mdsalManager, DataBroker dataBroker, AclserviceConfig config) {
74         super(FlowCapableNode.class, AclNodeListener.class);
75
76         this.mdsalManager = mdsalManager;
77         this.dataBroker = dataBroker;
78         this.config = config;
79     }
80
81     public void start() {
82         LOG.info("{} start", getClass().getSimpleName());
83         if (config != null) {
84             this.securityGroupMode = config.getSecurityGroupMode();
85         }
86         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
87         LOG.info("AclserviceConfig: {}", this.config);
88     }
89
90     /*
91      * (non-Javadoc)
92      *
93      * @see
94      * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
95      * getWildCardPath()
96      */
97     @Override
98     protected InstanceIdentifier<FlowCapableNode> getWildCardPath() {
99         return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
100     }
101
102     /*
103      * (non-Javadoc)
104      *
105      * @see
106      * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
107      * remove(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
108      * org.opendaylight.yangtools.yang.binding.DataObject)
109      */
110     @Override
111     protected void remove(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
112         // do nothing
113
114     }
115
116     /*
117      * (non-Javadoc)
118      *
119      * @see
120      * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
121      * update(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
122      * org.opendaylight.yangtools.yang.binding.DataObject,
123      * org.opendaylight.yangtools.yang.binding.DataObject)
124      */
125     @Override
126     protected void update(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModificationBefore,
127             FlowCapableNode dataObjectModificationAfter) {
128         // do nothing
129
130     }
131
132     /*
133      * (non-Javadoc)
134      *
135      * @see
136      * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
137      * add(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
138      * org.opendaylight.yangtools.yang.binding.DataObject)
139      */
140     @Override
141     protected void add(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
142         LOG.trace("FlowCapableNode Added: key: {}", key);
143         if (!AclClusterUtil.isEntityOwner()) {
144             return;
145         }
146         NodeKey nodeKey = key.firstKeyOf(Node.class);
147         BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
148         createTableDefaultEntries(dpnId);
149     }
150
151     /**
152      * Creates the table miss entries.
153      *
154      * @param dpnId the dpn id
155      */
156     private void createTableDefaultEntries(BigInteger dpnId) {
157         LOG.info("Adding default ACL entries for mode: "
158                 + (securityGroupMode == null ? SecurityGroupMode.Stateful : securityGroupMode));
159         if (securityGroupMode == null || securityGroupMode == SecurityGroupMode.Stateful) {
160             addIngressAclTableMissFlow(dpnId);
161             addEgressAclTableMissFlow(dpnId);
162             addConntrackRules(dpnId, NwConstants.LPORT_DISPATCHER_TABLE, NwConstants.INGRESS_ACL_FILTER_TABLE,
163                     NwConstants.ADD_FLOW);
164             addConntrackRules(dpnId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, NwConstants.EGRESS_ACL_FILTER_TABLE,
165                     NwConstants.ADD_FLOW);
166         } else if (securityGroupMode == SecurityGroupMode.Transparent) {
167             addTransparentIngressAclTableMissFlow(dpnId);
168             addTransparentEgressAclTableMissFlow(dpnId);
169         } else if (securityGroupMode == SecurityGroupMode.Stateless) {
170             addStatelessIngressAclTableMissFlow(dpnId);
171             addStatelessEgressAclTableMissFlow(dpnId);
172         } else if (securityGroupMode == SecurityGroupMode.Learn) {
173             addLearnIngressAclTableMissFlow(dpnId);
174             addLearnEgressAclTableMissFlow(dpnId);
175         }
176     }
177
178     /**
179      * Adds the ingress acl table miss flow.
180      *
181      * @param dpId the dp id
182      */
183     private void addIngressAclTableMissFlow(BigInteger dpId) {
184         List<MatchInfo> mkMatches = new ArrayList<>();
185         List<InstructionInfo> mkInstructions = new ArrayList<>();
186         List<ActionInfo> actionsInfos = new ArrayList<>();
187         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
188         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
189
190         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
191                 getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Ingress ACL Table Miss Flow", 0, 0,
192                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
193         mdsalManager.installFlow(flowEntity);
194
195         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
196                 getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0, "Ingress ACL Filter Table Miss Flow",
197                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
198         mdsalManager.installFlow(nextTblFlowEntity);
199
200         LOG.debug("Added Ingress ACL Table Miss Flows for dpn {}", dpId);
201     }
202
203     private void addLearnEgressAclTableMissFlow(BigInteger dpId) {
204         List<InstructionInfo> mkInstructions = new ArrayList<>();
205         List<ActionInfo> actionsInfos = new ArrayList<>();
206         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
207                 new String[] {Short.toString(NwConstants.EGRESS_LEARN_TABLE) }));
208         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
209                 new String[] {Short.toString(NwConstants.EGRESS_LEARN2_TABLE) }));
210         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
211
212         List<MatchInfo> mkMatches = new ArrayList<>();
213         FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
214                 "RESUB-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
215                 AclConstants.PROTO_MATCH_PRIORITY, "Egress resubmit ACL Table Block", 0, 0,
216                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
217         mdsalManager.installFlow(doubleResubmitTable);
218
219         mkMatches = new ArrayList<>();
220         mkInstructions = new ArrayList<>();
221         actionsInfos = new ArrayList<>();
222         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
223         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
224
225         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN_TABLE,
226                 "LEARN-" + getTableMissFlowId(NwConstants.EGRESS_LEARN_TABLE), 0,
227                 "Egress Learn ACL Table Miss Flow", 0, 0,
228                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
229         mdsalManager.installFlow(flowEntity);
230
231         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN2_TABLE,
232                 "LEARN-" + getTableMissFlowId(NwConstants.EGRESS_LEARN2_TABLE), 0,
233                 "Egress 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_6,
239                 new long[] {Long.valueOf(AclConstants.LEARN_MATCH_REG_VALUE)}));
240
241         short dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
242         List<InstructionInfo> instructions = new ArrayList<>();
243         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
244         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
245
246         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN2_TABLE,
247                 "LEARN2-REG-" + getTableMissFlowId(NwConstants.EGRESS_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     private void addLearnIngressAclTableMissFlow(BigInteger dpId) {
255         List<InstructionInfo> mkInstructions = new ArrayList<>();
256         List<ActionInfo> actionsInfos = new ArrayList<>();
257         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
258                 new String[] {Short.toString(NwConstants.INGRESS_LEARN_TABLE) }));
259         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
260                 new String[] {Short.toString(NwConstants.INGRESS_LEARN2_TABLE) }));
261         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
262
263         List<MatchInfo> mkMatches = new ArrayList<>();
264         FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
265                 "RESUB-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
266                 AclConstants.PROTO_MATCH_PRIORITY, "Ingress resubmit ACL Table Block", 0, 0,
267                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
268         mdsalManager.installFlow(doubleResubmitTable);
269
270         mkMatches = new ArrayList<>();
271         mkInstructions = new ArrayList<>();
272         actionsInfos = new ArrayList<>();
273         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
274         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
275
276         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN_TABLE,
277                 "LEARN-" + getTableMissFlowId(NwConstants.INGRESS_LEARN_TABLE), 0,
278                 "Ingress Learn ACL Table Miss Flow", 0, 0,
279                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
280         mdsalManager.installFlow(flowEntity);
281
282         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN2_TABLE,
283                 "LEARN-" + getTableMissFlowId(NwConstants.INGRESS_LEARN2_TABLE), 0,
284                 "Ingress Learn2 ACL Table Miss Flow", 0, 0,
285                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
286         mdsalManager.installFlow(flowEntity);
287
288         List<NxMatchInfo> nxMkMatches = new ArrayList<>();
289         nxMkMatches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_6,
290                 new long[] {Long.valueOf(AclConstants.LEARN_MATCH_REG_VALUE)}));
291
292         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
293         List<InstructionInfo> instructions = new ArrayList<>();
294         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
295         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
296
297         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN2_TABLE,
298                 "LEARN2-REG-" + getTableMissFlowId(NwConstants.INGRESS_LEARN2_TABLE),
299                 AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
300                 AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
301         mdsalManager.installFlow(flowEntity);
302         LOG.debug("Added learn ACL Table Miss Flows for dpn {}", dpId);
303
304     }
305
306     /**
307      * Adds the ingress acl table transparent flow.
308      *
309      * @param dpId the dp id
310      */
311     private void addTransparentIngressAclTableMissFlow(BigInteger dpId) {
312         List<MatchInfo> mkMatches = new ArrayList<>();
313         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
314         allowAllInstructions.add(
315             new InstructionInfo(InstructionType.goto_table,
316                     new long[] { NwConstants.INGRESS_ACL_FILTER_TABLE }));
317
318         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
319                 getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Ingress ACL Table allow all Flow",
320                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
321         mdsalManager.installFlow(nextTblFlowEntity);
322
323         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
324
325         List<ActionInfo> actionsInfos = new ArrayList<>();
326         List<InstructionInfo> dispatcherInstructions = new ArrayList<>();
327         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
328         dispatcherInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
329
330         nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
331                 getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0, "Ingress ACL Filter Table allow all Flow",
332                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, dispatcherInstructions);
333         mdsalManager.installFlow(nextTblFlowEntity);
334
335         LOG.debug("Added Transparent Ingress ACL Table allow all Flows for dpn {}", dpId);
336     }
337
338     /**
339      * Adds the egress acl table transparent flow.
340      *
341      * @param dpId the dp id
342      */
343     private void addTransparentEgressAclTableMissFlow(BigInteger dpId) {
344         List<MatchInfo> mkMatches = new ArrayList<>();
345         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
346         allowAllInstructions.add(
347             new InstructionInfo(InstructionType.goto_table,
348                     new long[] { NwConstants.EGRESS_ACL_FILTER_TABLE }));
349
350         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
351                 getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Egress ACL Table allow all Flow",
352                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
353         mdsalManager.installFlow(nextTblFlowEntity);
354
355         short dispatcherTableId =  NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
356
357         List<ActionInfo> actionsInfos = new ArrayList<>();
358         List<InstructionInfo> instructions = new ArrayList<>();
359         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
360         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
361
362         nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
363                 getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0, "Egress ACL Filter Table allow all Flow",
364                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, instructions);
365         mdsalManager.installFlow(nextTblFlowEntity);
366
367         LOG.debug("Added Transparent Egress ACL Table allow all Flows for dpn {}", dpId);
368     }
369
370     /**
371      * Adds the ingress acl table miss flow.
372      *
373      * @param dpId the dp id
374      */
375     private void addStatelessIngressAclTableMissFlow(BigInteger dpId) {
376         List<MatchInfo> synMatches = new ArrayList<>();
377         synMatches.add(new MatchInfo(MatchFieldType.eth_type,
378                 new long[] { NwConstants.ETHTYPE_IPV4 }));
379         synMatches.add(new MatchInfo(MatchFieldType.ip_proto,
380                 new long[] { IPProtocols.TCP.intValue() }));
381
382         synMatches.add(new MatchInfo(MatchFieldType.tcp_flags, new long[] { AclConstants.TCP_FLAG_SYN }));
383
384         List<ActionInfo> dropActionsInfos = new ArrayList<>();
385         dropActionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
386         List<InstructionInfo> synInstructions = new ArrayList<>();
387         synInstructions.add(new InstructionInfo(InstructionType.apply_actions, dropActionsInfos));
388
389         FlowEntity synFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
390                 "SYN-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
391                 AclConstants.PROTO_MATCH_SYN_DROP_PRIORITY, "Ingress Syn ACL Table Block", 0, 0,
392                 AclConstants.COOKIE_ACL_BASE, synMatches, synInstructions);
393         mdsalManager.installFlow(synFlowEntity);
394
395         synMatches = new ArrayList<>();
396         synMatches.add(new MatchInfo(MatchFieldType.eth_type,
397                 new long[] { NwConstants.ETHTYPE_IPV4 }));
398         synMatches.add(new MatchInfo(MatchFieldType.ip_proto,
399                 new long[] { IPProtocols.TCP.intValue() }));
400         synMatches.add(new MatchInfo(MatchFieldType.tcp_flags, new long[] { AclConstants.TCP_FLAG_SYN_ACK }));
401
402         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
403         allowAllInstructions.add(
404             new InstructionInfo(InstructionType.goto_table,
405                     new long[] { NwConstants.EGRESS_ACL_FILTER_TABLE }));
406
407         FlowEntity synAckFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
408                 "SYN-ACK-ALLOW-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
409                 AclConstants.PROTO_MATCH_SYN_ACK_ALLOW_PRIORITY, "Ingress Syn Ack ACL Table Allow", 0, 0,
410                 AclConstants.COOKIE_ACL_BASE, synMatches, allowAllInstructions);
411         mdsalManager.installFlow(synAckFlowEntity);
412
413
414         List<MatchInfo> mkMatches = new ArrayList<>();
415         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
416                 getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Ingress Stateless ACL Table Miss Flow",
417                 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
418         mdsalManager.installFlow(flowEntity);
419
420         short dispatcherTableId =  NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
421
422         List<ActionInfo> actionsInfos = new ArrayList<>();
423         List<InstructionInfo> instructions = new ArrayList<>();
424         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
425         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
426
427         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
428                 getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0,
429                 "Ingress Stateless Next ACL Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE,
430                 mkMatches, instructions);
431         mdsalManager.installFlow(nextTblFlowEntity);
432
433         LOG.debug("Added Stateless Ingress ACL Table Miss Flows for dpn {}.", dpId);
434     }
435
436     /**
437      * Adds the stateless egress acl table miss flow.
438      *
439      * @param dpId the dp id
440      */
441     private void addStatelessEgressAclTableMissFlow(BigInteger dpId) {
442         List<InstructionInfo> allowAllInstructions = new ArrayList<>();
443         allowAllInstructions.add(
444                 new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.INGRESS_ACL_FILTER_TABLE }));
445
446         List<MatchInfo> synMatches = new ArrayList<>();
447         synMatches.add(new MatchInfo(MatchFieldType.eth_type,
448                 new long[] { NwConstants.ETHTYPE_IPV4 }));
449         synMatches.add(new MatchInfo(MatchFieldType.ip_proto,
450                 new long[] { IPProtocols.TCP.intValue() }));
451         synMatches.add(new MatchInfo(MatchFieldType.tcp_flags, new long[] { AclConstants.TCP_FLAG_SYN }));
452
453         List<ActionInfo> synActionsInfos = new ArrayList<>();
454         synActionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
455         List<InstructionInfo> synInstructions = new ArrayList<>();
456         synInstructions.add(new InstructionInfo(InstructionType.apply_actions, synActionsInfos));
457
458         FlowEntity synFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
459                 "SYN-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
460                 AclConstants.PROTO_MATCH_SYN_DROP_PRIORITY, "Egress Syn ACL Table Block", 0, 0,
461                 AclConstants.COOKIE_ACL_BASE, synMatches, synInstructions);
462         mdsalManager.installFlow(synFlowEntity);
463
464         synMatches = new ArrayList<>();
465         synMatches.add(new MatchInfo(MatchFieldType.eth_type,
466                 new long[] { NwConstants.ETHTYPE_IPV4 }));
467         synMatches.add(new MatchInfo(MatchFieldType.ip_proto,
468                 new long[] { IPProtocols.TCP.intValue() }));
469         synMatches.add(new MatchInfo(MatchFieldType.tcp_flags, new long[] { AclConstants.TCP_FLAG_SYN_ACK }));
470
471         FlowEntity synAckFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
472                 "SYN-ACK-ALLOW-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
473                 AclConstants.PROTO_MATCH_SYN_ACK_ALLOW_PRIORITY, "Egress Syn Ack ACL Table Allow", 0, 0,
474                 AclConstants.COOKIE_ACL_BASE, synMatches, allowAllInstructions);
475         mdsalManager.installFlow(synAckFlowEntity);
476
477         List<MatchInfo> mkMatches = new ArrayList<>();
478         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
479                 getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Egress Stateless ACL Table Miss Flow", 0, 0,
480                 AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
481         mdsalManager.installFlow(flowEntity);
482
483         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
484
485         List<ActionInfo> actionsInfos = new ArrayList<>();
486         List<InstructionInfo> dispatcherInstructions = new ArrayList<>();
487         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
488         dispatcherInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
489
490         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
491                 getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0,
492                 "Egress Stateless Next ACL Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches,
493                 dispatcherInstructions);
494         mdsalManager.installFlow(nextTblFlowEntity);
495
496         LOG.debug("Added Stateless Egress ACL Table Miss Flows for dpn {}", dpId);
497     }
498
499     /**
500      * Adds the egress acl table miss flow.
501      *
502      * @param dpId the dp id
503      */
504     private void addEgressAclTableMissFlow(BigInteger dpId) {
505         List<MatchInfo> mkMatches = new ArrayList<>();
506         List<InstructionInfo> mkInstructions = new ArrayList<>();
507         List<ActionInfo> actionsInfos = new ArrayList<>();
508         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
509         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
510
511         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
512                 getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Egress ACL Table Miss Flow", 0, 0,
513                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
514         mdsalManager.installFlow(flowEntity);
515
516         FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
517                 getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0, "Egress ACL Table Miss Flow", 0, 0,
518                 AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
519         mdsalManager.installFlow(nextTblFlowEntity);
520
521         LOG.debug("Added Egress ACL Table Miss Flows for dpn {}", dpId);
522     }
523
524     private void addConntrackRules(BigInteger dpnId, short dispatcherTableId,short tableId, int write) {
525         programConntrackForwardRule(dpnId, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,
526             "Tracked_Established", AclConstants.TRACKED_EST_CT_STATE, AclConstants.TRACKED_EST_CT_STATE_MASK,
527             dispatcherTableId, tableId, write );
528         programConntrackForwardRule(dpnId, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,"Tracked_Related", AclConstants
529             .TRACKED_REL_CT_STATE, AclConstants.TRACKED_REL_CT_STATE_MASK, dispatcherTableId, tableId, write );
530         programConntrackDropRule(dpnId, AclConstants.CT_STATE_NEW_PRIORITY_DROP,"Tracked_New",
531             AclConstants.TRACKED_NEW_CT_STATE, AclConstants.TRACKED_NEW_CT_STATE_MASK, tableId, write );
532         programConntrackDropRule(dpnId, AclConstants.CT_STATE_NEW_PRIORITY_DROP, "Tracked_Invalid",
533             AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, tableId, write );
534
535     }
536
537     /**
538      * Adds the rule to forward the packets known packets.
539      *
540      * @param dpId the dpId
541      * @param lportTag the lport tag
542      * @param priority the priority of the flow
543      * @param flowId the flowId
544      * @param conntrackState the conntrack state of the packets thats should be
545      *        send
546      * @param conntrackMask the conntrack mask
547      * @param addOrRemove whether to add or remove the flow
548      */
549     private void programConntrackForwardRule(BigInteger dpId, Integer priority, String flowId,
550             int conntrackState, int conntrackMask, short dispatcherTableId, short tableId, int addOrRemove) {
551         List<MatchInfoBase> matches = new ArrayList<>();
552         matches.add(new NxMatchInfo(NxMatchFieldType.ct_state, new long[] {conntrackState, conntrackMask}));
553
554         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(
555             new ArrayList<>(),dispatcherTableId);
556
557         flowId = "Fixed_Conntrk_Trk_" + dpId + "_" + flowId + dispatcherTableId;
558         syncFlow(dpId, tableId, flowId, priority, "ACL", 0, 0,
559                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
560     }
561
562     /**
563      * Adds the rule to drop the unknown/invalid packets .
564      *
565      * @param dpId the dpId
566      * @param lportTag the lport tag
567      * @param priority the priority of the flow
568      * @param flowId the flowId
569      * @param conntrackState the conntrack state of the packets thats should be
570      *        send
571      * @param conntrackMask the conntrack mask
572      * @param addOrRemove whether to add or remove the flow
573      */
574     private void programConntrackDropRule(BigInteger dpId, Integer priority, String flowId,
575             int conntrackState, int conntrackMask, short tableId, int addOrRemove) {
576         List<MatchInfoBase> matches = new ArrayList<>();
577         matches.add(new NxMatchInfo(NxMatchFieldType.ct_state, new long[] {conntrackState, conntrackMask}));
578
579         List<InstructionInfo> instructions = new ArrayList<>();
580         List<ActionInfo> actionsInfos = new ArrayList<>();
581         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
582         instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
583         flowId = "Fixed_Conntrk_NewDrop_" + dpId + "_" + flowId + tableId;
584         syncFlow(dpId, tableId, flowId, priority, "ACL", 0, 0,
585                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
586     }
587
588     /**
589      * Gets the dispatcher table resubmit instructions.
590      *
591      * @param actionsInfos the actions infos
592      * @return the instructions for dispatcher table resubmit
593      */
594     private List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos,
595                                                                          short dispatcherTableId) {
596         List<InstructionInfo> instructions = new ArrayList<>();
597         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
598         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
599         return instructions;
600     }
601
602     /**
603      * Writes/remove the flow to/from the datastore.
604      * @param dpId the dpId
605      * @param tableId the tableId
606      * @param flowId the flowId
607      * @param priority the priority
608      * @param flowName the flow name
609      * @param idleTimeOut the idle timeout
610      * @param hardTimeOut the hard timeout
611      * @param cookie the cookie
612      * @param matches the list of matches to be written
613      * @param instructions the list of instruction to be written.
614      * @param addOrRemove add or remove the entries.
615      */
616     protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
617                           int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase>  matches,
618                           List<InstructionInfo> instructions, int addOrRemove) {
619         if (addOrRemove == NwConstants.DEL_FLOW) {
620             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,flowId,
621                 priority, flowName , idleTimeOut, hardTimeOut, cookie, matches, null);
622             LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
623             mdsalManager.removeFlow(flowEntity);
624         } else {
625             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId,
626                 priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions);
627             LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
628             mdsalManager.installFlow(flowEntity);
629         }
630     }
631
632     /**
633      * Gets the table miss flow id.
634      *
635      * @param tableId the table id
636      * @return the table miss flow id
637      */
638     private String getTableMissFlowId(short tableId) {
639         return String.valueOf(tableId);
640     }
641
642     /*
643      * (non-Javadoc)
644      *
645      * @see
646      * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
647      * getDataTreeChangeListener()
648      */
649     @Override
650     protected AclNodeListener getDataTreeChangeListener() {
651         return AclNodeListener.this;
652     }
653 }