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