Update broadcast rules for subnet addtion/deletion
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / IngressAclServiceImpl.java
1 /*
2  * Copyright (c) 2018 Red Hat, Inc. 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 package org.opendaylight.netvirt.aclservice;
9
10 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.genius.mdsalutil.FlowEntity;
19 import org.opendaylight.genius.mdsalutil.InstructionInfo;
20 import org.opendaylight.genius.mdsalutil.MDSALUtil;
21 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
22 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
23 import org.opendaylight.genius.mdsalutil.NwConstants;
24 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
25 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
26 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
27 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
28 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
29 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
30 import org.opendaylight.genius.utils.ServiceIndex;
31 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
32 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
33 import org.opendaylight.netvirt.aclservice.api.AclServiceManager;
34 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
35 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
36 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
37 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
38 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
39 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
40 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 /**
57  * Provides the implementation for ingress (w.r.t VM) ACL service.
58  *
59  * <p>
60  * Note: Table names used are w.r.t switch. Hence, switch ingress is VM egress
61  * and vice versa.
62  */
63 public class IngressAclServiceImpl extends AbstractAclServiceImpl {
64
65     private static final Logger LOG = LoggerFactory.getLogger(IngressAclServiceImpl.class);
66
67     /**
68      * Initialize the member variables.
69      *
70      * @param dataBroker the data broker instance.
71      * @param mdsalManager the mdsal manager.
72      * @param aclDataUtil the acl data util.
73      * @param aclServiceUtils the acl service util.
74      * @param jobCoordinator the job coordinator
75      * @param aclInterfaceCache the acl interface cache
76      */
77     public IngressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil,
78             AclServiceUtils aclServiceUtils, JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
79         // Service mode is w.rt. switch
80         super(ServiceModeEgress.class, dataBroker, mdsalManager, aclDataUtil, aclServiceUtils, jobCoordinator,
81                 aclInterfaceCache);
82     }
83
84     /**
85      * Bind service.
86      *
87      * @param aclInterface the acl interface
88      */
89     @Override
90     public void bindService(AclInterface aclInterface) {
91         String interfaceName = aclInterface.getInterfaceId();
92         jobCoordinator.enqueueJob(interfaceName, () -> {
93             int instructionKey = 0;
94             List<Instruction> instructions = new ArrayList<>();
95             instructions.add(
96                     MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.EGRESS_ACL_DUMMY_TABLE, ++instructionKey));
97             int flowPriority = NwConstants.EGRESS_ACL_SERVICE_INDEX;
98             short serviceIndex =
99                     ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX);
100             BoundServices serviceInfo =
101                     AclServiceUtils.getBoundServices(String.format("%s.%s.%s", "acl", "egressacl", interfaceName),
102                             serviceIndex, flowPriority, AclConstants.COOKIE_ACL_BASE, instructions);
103             InstanceIdentifier<BoundServices> path = AclServiceUtils.buildServiceId(interfaceName,
104                     ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX),
105                     serviceMode);
106
107             return Collections.singletonList(
108                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.put(
109                             path, serviceInfo, CREATE_MISSING_PARENTS)));
110         });
111     }
112
113     /**
114      * Unbind service.
115      *
116      * @param aclInterface the acl interface
117      */
118     @Override
119     protected void unbindService(AclInterface aclInterface) {
120         String interfaceName = aclInterface.getInterfaceId();
121         InstanceIdentifier<BoundServices> path = AclServiceUtils.buildServiceId(interfaceName,
122                 ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX),
123                 serviceMode);
124
125         LOG.debug("UnBinding ACL service for interface {}", interfaceName);
126         jobCoordinator.enqueueJob(interfaceName, () -> Collections.singletonList(txRunner
127                 .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path))));
128     }
129
130     @Override
131     protected void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
132             List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
133         LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
134                 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
135
136         BigInteger dpid = port.getDpId();
137         int lportTag = port.getLPortTag();
138         if (action == Action.ADD || action == Action.REMOVE) {
139             programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
140             ingressAclDhcpAllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
141             ingressAclDhcpv6AllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
142             ingressAclIcmpv6AllowedTraffic(flowEntries, port, addOrRemove);
143             programIcmpv6RARule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
144
145             programArpRule(flowEntries, dpid, lportTag, addOrRemove);
146             programIpv4BroadcastRule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
147         }
148     }
149
150     private void programCommitterDropFlow(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
151             int addOrRemove) {
152         List<MatchInfoBase> matches = new ArrayList<>();
153         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
154
155         BigInteger metaData = MetaDataUtil.METADATA_MASK_ACL_DROP
156                 .and(AclConstants.METADATA_DROP_FLAG.shiftLeft(2));
157         BigInteger metaDataMask = MetaDataUtil.METADATA_MASK_ACL_DROP
158                 .and(AclConstants.METADATA_DROP_FLAG.shiftLeft(2));
159         matches.add(new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
160                 MetaDataUtil.getLportTagMaskForReg6()));
161         matches.add(new MatchMetadata(metaData, metaDataMask));
162
163         String flowName = "Ingress_" + dpId + "_" + lportTag + "_Drop";
164         addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName,
165                 AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
166                 matches, instructions, addOrRemove);
167     }
168
169     @Override
170     protected void programGotoClassifierTableRules(List<FlowEntity> flowEntries, BigInteger dpId,
171             List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove) {
172         for (AllowedAddressPairs aap : aaps) {
173             IpPrefixOrAddress attachIp = aap.getIpAddress();
174             MacAddress mac = aap.getMacAddress();
175
176             List<MatchInfoBase> matches = new ArrayList<>();
177             matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
178             matches.add(new MatchEthernetDestination(mac));
179             matches.addAll(AclServiceUtils.buildIpMatches(attachIp, MatchCriteria.MATCH_DESTINATION));
180
181             List<InstructionInfo> gotoInstructions = new ArrayList<>();
182             gotoInstructions.add(new InstructionGotoTable(getAclConntrackClassifierTable()));
183
184             String flowName = "Ingress_Fixed_Goto_Classifier_" + dpId + "_" + lportTag + "_" + mac.getValue() + "_"
185                     + attachIp.stringValue();
186             addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
187                     AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, gotoInstructions,
188                     addOrRemove);
189         }
190     }
191
192     @Override
193     protected void programRemoteAclTableFlow(List<FlowEntity> flowEntries, BigInteger dpId, Integer aclTag,
194             AllowedAddressPairs aap, int addOrRemove) {
195         List<MatchInfoBase> flowMatches = new ArrayList<>();
196         flowMatches.addAll(AclServiceUtils.buildIpAndSrcServiceMatch(aclTag, aap));
197
198         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
199         String flowNameAdded = "Acl_Filter_Ingress_" + aap.getIpAddress().stringValue() + "_" + aclTag;
200
201         addFlowEntryToList(flowEntries, dpId, getAclRemoteAclTable(), flowNameAdded, AclConstants.ACL_DEFAULT_PRIORITY,
202                 0, 0, AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove);
203     }
204
205     /**
206      * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
207      *
208      * @param flowEntries the flow entries
209      * @param dpId the dpid
210      * @param lportTag the lport tag
211      * @param addOrRemove is write or delete
212      */
213     protected void ingressAclDhcpAllowServerTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
214             int addOrRemove) {
215         final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
216                 AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, serviceMode);
217         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
218
219         String flowName = "Ingress_DHCP_Server_v4" + dpId + "_" + lportTag + "_Permit_";
220         addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
221                 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
222                 instructions, addOrRemove);
223     }
224
225     /**
226      * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed.
227      *
228      * @param flowEntries the flow entries
229      * @param dpId the dpid
230      * @param lportTag the lport tag
231      * @param addOrRemove is write or delete
232      */
233     protected void ingressAclDhcpv6AllowServerTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
234             int addOrRemove) {
235         final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
236                 AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, serviceMode);
237         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
238
239         String flowName = "Ingress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_Permit_";
240         addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
241                 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
242                 instructions, addOrRemove);
243     }
244
245     /**
246      * Add rules to ensure that certain ICMPv6 like MLD_QUERY (130), RS (134), NS (135), NA (136) are
247      * allowed into the VM.
248      *
249      * @param flowEntries the flow entries
250      * @param port the port
251      * @param addOrRemove is write or delete
252      */
253     private void ingressAclIcmpv6AllowedTraffic(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
254         BigInteger dpId = port.getDpId();
255         int lportTag = port.getLPortTag();
256         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
257
258         // Allow ICMPv6 Multicast Listener Query packets.
259         List<MatchInfoBase> matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_MLD_QUERY, 0,
260                 lportTag, serviceMode);
261
262         final short tableId = getAclAntiSpoofingTable();
263         String flowName =
264                 "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_MLD_QUERY + "_Permit_";
265         addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
266                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
267
268         // Allow ICMPv6 Neighbor Solicitation packets.
269         matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NS, 0, lportTag, serviceMode);
270
271         flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NS + "_Permit_";
272         addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
273                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
274
275         // Allow ICMPv6 Neighbor Advertisement packets.
276         matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NA, 0, lportTag, serviceMode);
277
278         flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NA + "_Permit_";
279         addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
280                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
281     }
282
283     @Override
284     protected void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port, List<SubnetInfo> subnets,
285             int addOrRemove) {
286         if (AclServiceUtils.isIpv6Subnet(subnets)) {
287             /* Allow ICMPv6 Router Advertisement packets from external routers as well as internal routers
288              * if subnet is configured with IPv6 version
289              * Allow ICMPv6 Router Advertisement packets if originating from any LinkLocal Address.
290              */
291             List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
292             List<MatchInfoBase> matches =
293                     AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_RA, 0,
294                             port.getLPortTag(), serviceMode);
295             matches.addAll(AclServiceUtils.buildIpMatches(
296                     new IpPrefixOrAddress(IpPrefixBuilder.getDefaultInstance(AclConstants.IPV6_LINK_LOCAL_PREFIX)),
297                     AclServiceManager.MatchCriteria.MATCH_SOURCE));
298             String flowName = "Ingress_ICMPv6" + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
299                     + AclConstants.ICMPV6_TYPE_RA + "_LinkLocal_Permit_";
300             addFlowEntryToList(flowEntries, port.getDpId(), getAclAntiSpoofingTable(), flowName,
301                     AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
302                     instructions, addOrRemove);
303         }
304     }
305
306     /**
307      * Adds the rule to allow arp packets.
308      *
309      * @param flowEntries the flow entries
310      * @param dpId the dpId
311      * @param lportTag the lport tag
312      * @param addOrRemove whether to add or remove the flow
313      */
314     protected void programArpRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag, int addOrRemove) {
315         List<MatchInfoBase> matches = new ArrayList<>();
316         matches.add(MatchEthernetType.ARP);
317         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
318         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
319         LOG.debug("{} ARP Rule on DPID {}, lportTag {}", addOrRemove == NwConstants.DEL_FLOW ? "Deleting" : "Adding",
320                 dpId, lportTag);
321         String flowName = "Ingress_ARP_" + dpId + "_" + lportTag;
322         addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
323                 AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
324                 instructions, addOrRemove);
325     }
326
327
328     /**
329      * Programs broadcast rules.
330      *
331      * @param flowEntries the flow entries
332      * @param port the Acl Interface port
333      * @param addOrRemove whether to delete or add flow
334      */
335     @Override
336     protected void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
337         programIpv4BroadcastRule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
338     }
339
340     /**
341      * Programs broadcast rules.
342      *
343      * @param flowEntries the flow entries
344      * @param port the Acl Interface port
345      * @param subnetInfoList the port subnet info list
346      * @param addOrRemove whether to delete or add flow
347      */
348     protected void programSubnetBroadcastRules(List<FlowEntity> flowEntries, AclInterface port,
349             List<SubnetInfo> subnetInfoList, int addOrRemove) {
350         programIpv4BroadcastRule(flowEntries, port, subnetInfoList, addOrRemove);
351     }
352
353     /**
354      * Programs IPv4 broadcast rules.
355      *
356      * @param flowEntries the flow entries
357      * @param port the Acl Interface port
358      * @param subnetInfoList Port subnet list
359      * @param addOrRemove whether to delete or add flow
360      */
361     private void programIpv4BroadcastRule(List<FlowEntity> flowEntries, AclInterface port,
362             List<SubnetInfo> subnetInfoList, int addOrRemove) {
363         BigInteger dpId = port.getDpId();
364         int lportTag = port.getLPortTag();
365         MatchInfoBase lportMatchInfo = AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode);
366         if (subnetInfoList != null) {
367             List<String> broadcastAddresses = AclServiceUtils.getIpBroadcastAddresses(subnetInfoList);
368             for (String broadcastAddress : broadcastAddresses) {
369                 List<MatchInfoBase> matches =
370                         AclServiceUtils.buildBroadcastIpV4Matches(broadcastAddress);
371                 matches.add(lportMatchInfo);
372                 List<InstructionInfo> instructions = new ArrayList<>();
373                 instructions.add(new InstructionGotoTable(getAclConntrackClassifierTable()));
374                 String flowName = "Ingress_v4_Broadcast_" + dpId + "_" + lportTag + "_" + broadcastAddress + "_Permit";
375                 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
376                         AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
377                         addOrRemove);
378             }
379         } else {
380             LOG.warn("IP Broadcast CIDRs are missing for port {}", port.getInterfaceId());
381         }
382     }
383
384     @Override
385     protected boolean isValidDirection(Class<? extends DirectionBase> direction) {
386         return direction.equals(DirectionIngress.class);
387     }
388
389     private short getAclAntiSpoofingTable() {
390         return NwConstants.EGRESS_ACL_ANTI_SPOOFING_TABLE;
391     }
392
393     private short getAclConntrackClassifierTable() {
394         return NwConstants.EGRESS_ACL_CONNTRACK_CLASSIFIER_TABLE;
395     }
396
397     @Override
398     protected short getAclConntrackSenderTable() {
399         return NwConstants.EGRESS_ACL_CONNTRACK_SENDER_TABLE;
400     }
401
402     @Override
403     protected short getAclForExistingTrafficTable() {
404         return NwConstants.EGRESS_ACL_FOR_EXISTING_TRAFFIC_TABLE;
405     }
406
407     @Override
408     protected short getAclFilterCumDispatcherTable() {
409         return NwConstants.EGRESS_ACL_FILTER_CUM_DISPATCHER_TABLE;
410     }
411
412     @Override
413     protected short getAclRuleBasedFilterTable() {
414         return NwConstants.EGRESS_ACL_RULE_BASED_FILTER_TABLE;
415     }
416
417     @Override
418     protected short getAclRemoteAclTable() {
419         return NwConstants.EGRESS_REMOTE_ACL_TABLE;
420     }
421
422     @Override
423     protected short getAclCommitterTable() {
424         return NwConstants.EGRESS_ACL_COMMITTER_TABLE;
425     }
426 }