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