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