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