2 * Copyright (c) 2018 Red Hat, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.aclservice;
10 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import com.google.common.collect.Lists;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.genius.mdsalutil.FlowEntity;
21 import org.opendaylight.genius.mdsalutil.InstructionInfo;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.genius.mdsalutil.MatchInfo;
24 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
25 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
26 import org.opendaylight.genius.mdsalutil.NwConstants;
27 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
28 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
29 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
30 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
31 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv4;
32 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
33 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
34 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
35 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
36 import org.opendaylight.genius.utils.ServiceIndex;
37 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
38 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
39 import org.opendaylight.netvirt.aclservice.api.AclServiceManager;
40 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
41 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
42 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
43 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
44 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
45 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
46 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl.InterfaceType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
64 * Provides the implementation for ingress (w.r.t VM) ACL service.
67 * Note: Table names used are w.r.t switch. Hence, switch ingress is VM egress
70 public class IngressAclServiceImpl extends AbstractAclServiceImpl {
72 private static final Logger LOG = LoggerFactory.getLogger(IngressAclServiceImpl.class);
75 * Initialize the member variables.
77 * @param dataBroker the data broker instance.
78 * @param mdsalManager the mdsal manager.
79 * @param aclDataUtil the acl data util.
80 * @param aclServiceUtils the acl service util.
81 * @param jobCoordinator the job coordinator
82 * @param aclInterfaceCache the acl interface cache
84 public IngressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil,
85 AclServiceUtils aclServiceUtils, JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
86 // Service mode is w.rt. switch
87 super(ServiceModeEgress.class, dataBroker, mdsalManager, aclDataUtil, aclServiceUtils, jobCoordinator,
94 * @param aclInterface the acl interface
97 public void bindService(AclInterface aclInterface) {
98 String interfaceName = aclInterface.getInterfaceId();
99 jobCoordinator.enqueueJob(interfaceName, () -> {
100 int instructionKey = 0;
101 List<Instruction> instructions = new ArrayList<>();
103 MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.EGRESS_ACL_DUMMY_TABLE, ++instructionKey));
104 int flowPriority = NwConstants.EGRESS_ACL_SERVICE_INDEX;
106 ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX);
107 BoundServices serviceInfo =
108 AclServiceUtils.getBoundServices(String.format("%s.%s.%s", "acl", "egressacl", interfaceName),
109 serviceIndex, flowPriority, AclConstants.COOKIE_ACL_BASE, instructions);
110 InstanceIdentifier<BoundServices> path = AclServiceUtils.buildServiceId(interfaceName,
111 ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX),
114 return Collections.singletonList(
115 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.put(
116 path, serviceInfo, CREATE_MISSING_PARENTS)));
123 * @param aclInterface the acl interface
126 protected void unbindService(AclInterface aclInterface) {
127 String interfaceName = aclInterface.getInterfaceId();
128 InstanceIdentifier<BoundServices> path = AclServiceUtils.buildServiceId(interfaceName,
129 ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX),
132 LOG.debug("UnBinding ACL service for interface {}", interfaceName);
133 jobCoordinator.enqueueJob(interfaceName, () -> Collections.singletonList(txRunner
134 .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path))));
138 * Programs DHCP Service flows.
140 * @param flowEntries the flow entries
141 * @param port the acl interface
142 * @param action add/modify/remove action
143 * @param addOrRemove addorRemove
146 protected void programDhcpService(List<FlowEntity> flowEntries, AclInterface port,
147 Action action, int addOrRemove) {
148 LOG.info("{} programDhcpService for port {}, action={}, addOrRemove={}", this.directionString,
149 port.getInterfaceId(), action, addOrRemove);
150 BigInteger dpid = port.getDpId();
151 int lportTag = port.getLPortTag();
152 allowDhcpClientTraffic(flowEntries, dpid, lportTag, addOrRemove);
153 allowDhcpv6ClientTraffic(flowEntries, dpid, lportTag, addOrRemove);
154 programArpRule(flowEntries, dpid, lportTag, addOrRemove);
155 ingressAclIcmpv6AllowedTraffic(flowEntries, port, InterfaceType.DhcpService, addOrRemove);
156 allowIcmpTrafficToDhcpServer(flowEntries, port, port.getAllowedAddressPairs(), addOrRemove);
157 dropTrafficToDhcpServer(flowEntries, dpid, lportTag, addOrRemove);
158 programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
162 * Programs DHCP service flows.
164 * @param flowEntries the flow entries
165 * @param port the acl interface
166 * @param allowedAddresses the allowed addresses
167 * @param addOrRemove addorRemove
170 protected void processDhcpServiceUpdate(List<FlowEntity> flowEntries, AclInterface port,
171 List<AllowedAddressPairs> allowedAddresses, int addOrRemove) {
172 allowIcmpTrafficToDhcpServer(flowEntries, port, allowedAddresses, addOrRemove);
176 protected void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
177 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
178 LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
179 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
181 BigInteger dpid = port.getDpId();
182 int lportTag = port.getLPortTag();
183 if (action == Action.ADD || action == Action.REMOVE) {
184 programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
185 ingressAclDhcpAllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
186 ingressAclDhcpv6AllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
187 ingressAclIcmpv6AllowedTraffic(flowEntries, port, InterfaceType.AccessPort, addOrRemove);
188 programIcmpv6RARule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
190 programArpRule(flowEntries, dpid, lportTag, addOrRemove);
191 programIpv4BroadcastRule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
195 private void programCommitterDropFlow(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
197 List<MatchInfoBase> matches = new ArrayList<>();
198 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
200 BigInteger metaData = MetaDataUtil.METADATA_MASK_ACL_DROP
201 .and(AclConstants.METADATA_DROP_FLAG.shiftLeft(2));
202 BigInteger metaDataMask = MetaDataUtil.METADATA_MASK_ACL_DROP
203 .and(AclConstants.METADATA_DROP_FLAG.shiftLeft(2));
204 matches.add(new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
205 MetaDataUtil.getLportTagMaskForReg6()));
206 matches.add(new MatchMetadata(metaData, metaDataMask));
208 String flowName = "Ingress_" + dpId + "_" + lportTag + "_Drop";
209 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName,
210 AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
211 matches, instructions, addOrRemove);
215 protected void programGotoClassifierTableRules(List<FlowEntity> flowEntries, BigInteger dpId,
216 List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove) {
217 for (AllowedAddressPairs aap : aaps) {
218 IpPrefixOrAddress attachIp = aap.getIpAddress();
219 MacAddress mac = aap.getMacAddress();
221 List<MatchInfoBase> matches = new ArrayList<>();
222 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
223 matches.add(new MatchEthernetDestination(mac));
224 matches.addAll(AclServiceUtils.buildIpMatches(attachIp, MatchCriteria.MATCH_DESTINATION));
226 List<InstructionInfo> gotoInstructions = new ArrayList<>();
227 gotoInstructions.add(new InstructionGotoTable(getAclConntrackClassifierTable()));
229 String flowName = "Ingress_Fixed_Goto_Classifier_" + dpId + "_" + lportTag + "_" + mac.getValue() + "_"
230 + attachIp.stringValue();
231 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
232 AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, gotoInstructions,
238 protected void programRemoteAclTableFlow(List<FlowEntity> flowEntries, BigInteger dpId, Integer aclTag,
239 AllowedAddressPairs aap, int addOrRemove) {
240 List<MatchInfoBase> flowMatches = new ArrayList<>();
241 flowMatches.addAll(AclServiceUtils.buildIpAndSrcServiceMatch(aclTag, aap));
243 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
244 String flowNameAdded = "Acl_Filter_Ingress_" + aap.getIpAddress().stringValue() + "_" + aclTag;
246 addFlowEntryToList(flowEntries, dpId, getAclRemoteAclTable(), flowNameAdded, AclConstants.ACL_DEFAULT_PRIORITY,
247 0, 0, AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove);
251 * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
253 * @param flowEntries the flow entries
254 * @param dpId the dpid
255 * @param lportTag the lport tag
256 * @param addOrRemove is write or delete
258 protected void ingressAclDhcpAllowServerTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
260 final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
261 AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, serviceMode);
262 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
264 String flowName = "Ingress_DHCP_Server_v4" + dpId + "_" + lportTag + "_Permit_";
265 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
266 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
267 instructions, addOrRemove);
271 * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed.
273 * @param flowEntries the flow entries
274 * @param dpId the dpid
275 * @param lportTag the lport tag
276 * @param addOrRemove is write or delete
278 protected void ingressAclDhcpv6AllowServerTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
280 final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
281 AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, serviceMode);
282 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
284 String flowName = "Ingress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_Permit_";
285 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
286 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
287 instructions, addOrRemove);
291 * Add rules to ensure that certain ICMPv6 like MLD_QUERY (130), RS (134), NS (135), NA (136) are
292 * allowed into the VM.
294 * @param flowEntries the flow entries
295 * @param port the port
297 * @param addOrRemove is write or delete
299 private void ingressAclIcmpv6AllowedTraffic(List<FlowEntity> flowEntries, AclInterface port,
300 InterfaceType interfaceType, int addOrRemove) {
301 BigInteger dpId = port.getDpId();
302 int lportTag = port.getLPortTag();
303 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
305 final short tableId = getAclAntiSpoofingTable();
307 if (interfaceType != InterfaceType.DhcpService) {
308 // Allow ICMPv6 Multicast Listener Query packets.
309 List<MatchInfoBase> matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_MLD_QUERY, 0,
310 lportTag, serviceMode);
311 String flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_"
312 + AclConstants.ICMPV6_TYPE_MLD_QUERY + "_Permit_";
313 addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
314 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
317 // Allow ICMPv6 Neighbor Solicitation packets.
318 List<MatchInfoBase> matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NS, 0, lportTag,
321 String flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_"
322 + AclConstants.ICMPV6_TYPE_NS + "_Permit_";
323 addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
324 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
326 // Allow ICMPv6 Neighbor Advertisement packets.
327 matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NA, 0, lportTag, serviceMode);
329 flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NA + "_Permit_";
330 addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
331 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
335 protected void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port, List<SubnetInfo> subnets,
337 if (AclServiceUtils.isIpv6Subnet(subnets)) {
338 /* Allow ICMPv6 Router Advertisement packets from external routers as well as internal routers
339 * if subnet is configured with IPv6 version
340 * Allow ICMPv6 Router Advertisement packets if originating from any LinkLocal Address.
342 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
343 List<MatchInfoBase> matches =
344 AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_RA, 0,
345 port.getLPortTag(), serviceMode);
346 matches.addAll(AclServiceUtils.buildIpMatches(
347 new IpPrefixOrAddress(IpPrefixBuilder.getDefaultInstance(AclConstants.IPV6_LINK_LOCAL_PREFIX)),
348 AclServiceManager.MatchCriteria.MATCH_SOURCE));
349 String flowName = "Ingress_ICMPv6" + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
350 + AclConstants.ICMPV6_TYPE_RA + "_LinkLocal_Permit_";
351 addFlowEntryToList(flowEntries, port.getDpId(), getAclAntiSpoofingTable(), flowName,
352 AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
353 instructions, addOrRemove);
358 * Adds the rule to allow arp packets.
360 * @param flowEntries the flow entries
361 * @param dpId the dpId
362 * @param lportTag the lport tag
363 * @param addOrRemove whether to add or remove the flow
365 protected void programArpRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag, int addOrRemove) {
366 List<MatchInfoBase> matches = new ArrayList<>();
367 matches.add(MatchEthernetType.ARP);
368 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
369 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
370 LOG.debug("{} ARP Rule on DPID {}, lportTag {}", addOrRemove == NwConstants.DEL_FLOW ? "Deleting" : "Adding",
372 String flowName = "Ingress_ARP_" + dpId + "_" + lportTag;
373 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
374 AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
375 instructions, addOrRemove);
380 * Programs broadcast rules.
382 * @param flowEntries the flow entries
383 * @param port the Acl Interface port
384 * @param addOrRemove whether to delete or add flow
387 protected void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, Action action,
389 programIpv4BroadcastRule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
393 * Programs broadcast rules.
395 * @param flowEntries the flow entries
396 * @param port the Acl Interface port
397 * @param subnetInfoList the port subnet info list
398 * @param addOrRemove whether to delete or add flow
400 protected void programSubnetBroadcastRules(List<FlowEntity> flowEntries, AclInterface port,
401 List<SubnetInfo> subnetInfoList, int addOrRemove) {
402 programIpv4BroadcastRule(flowEntries, port, subnetInfoList, addOrRemove);
406 * Programs IPv4 broadcast rules.
408 * @param flowEntries the flow entries
409 * @param port the Acl Interface port
410 * @param subnetInfoList Port subnet list
411 * @param addOrRemove whether to delete or add flow
413 private void programIpv4BroadcastRule(List<FlowEntity> flowEntries, AclInterface port,
414 List<SubnetInfo> subnetInfoList, int addOrRemove) {
415 BigInteger dpId = port.getDpId();
416 int lportTag = port.getLPortTag();
417 MatchInfoBase lportMatchInfo = AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode);
418 if (subnetInfoList != null) {
419 List<String> broadcastAddresses = AclServiceUtils.getIpBroadcastAddresses(subnetInfoList);
420 for (String broadcastAddress : broadcastAddresses) {
421 List<MatchInfoBase> matches =
422 AclServiceUtils.buildBroadcastIpV4Matches(broadcastAddress);
423 matches.add(lportMatchInfo);
424 List<InstructionInfo> instructions = new ArrayList<>();
425 instructions.add(new InstructionGotoTable(getAclConntrackClassifierTable()));
426 String flowName = "Ingress_v4_Broadcast_" + dpId + "_" + lportTag + "_" + broadcastAddress + "_Permit";
427 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
428 AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
432 LOG.warn("IP Broadcast CIDRs are missing for port {}", port.getInterfaceId());
437 * Add rule to ensure only DHCP client traffic is allowed.
439 * @param flowEntries the flow entries
440 * @param dpId the dpid
441 * @param lportTag the lport tag
442 * @param addOrRemove is write or delete
444 protected void allowDhcpClientTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
446 final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_CLIENT_PORT_IPV4,
447 AclConstants.DHCP_SERVER_PORT_IPV4, lportTag, serviceMode);
448 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
450 String flowName = "Ingress_DHCP_Service_v4" + dpId + "_" + lportTag + "_Permit_";
451 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
452 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
453 instructions, addOrRemove);
457 * Add rule to ensure only DHCPv6 client traffic is allowed.
459 * @param flowEntries the flow entries
460 * @param dpId the dpid
461 * @param lportTag the lport tag
462 * @param addOrRemove is write or delete
464 protected void allowDhcpv6ClientTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
466 final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_CLIENT_PORT_IPV6,
467 AclConstants.DHCP_SERVER_PORT_IPV6, lportTag, serviceMode);
468 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
470 String flowName = "Ingress_DHCP_Service_v6" + "_" + dpId + "_" + lportTag + "_Permit_";
471 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
472 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
473 instructions, addOrRemove);
477 * Add rules to allow ICMP traffic for DHCP server.
478 * @param flowEntries the flow entries
479 * @param port the Acl Interface port
480 * @param allowedAddresses the allowed addresses
481 * @param addOrRemove the lport tag
483 protected void allowIcmpTrafficToDhcpServer(List<FlowEntity> flowEntries, AclInterface port,
484 List<AllowedAddressPairs> allowedAddresses, int addOrRemove) {
485 BigInteger dpId = port.getDpId();
486 int lportTag = port.getLPortTag();
487 for (AllowedAddressPairs allowedAddress : allowedAddresses) {
488 if (AclServiceUtils.isIPv4Address(allowedAddress)) {
489 MatchInfo reqMatchInfo = new MatchIcmpv4((short) AclConstants.ICMPV4_TYPE_ECHO_REQUEST, (short) 0);
490 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMP, reqMatchInfo,
491 AclConstants.ICMPV4_TYPE_ECHO_REQUEST, addOrRemove);
492 MatchInfo replyMatchInfo = new MatchIcmpv4((short) AclConstants.ICMPV4_TYPE_ECHO_REPLY, (short) 0);
493 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMP, replyMatchInfo,
494 AclConstants.ICMPV4_TYPE_ECHO_REPLY, addOrRemove);
496 MatchInfo reqMatchInfo = new MatchIcmpv6((short) AclConstants.ICMPV6_TYPE_ECHO_REQUEST, (short) 0);
497 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMPV6, reqMatchInfo,
498 AclConstants.ICMPV6_TYPE_ECHO_REQUEST, addOrRemove);
499 MatchInfo replyMatchInfo = new MatchIcmpv6((short) AclConstants.ICMPV6_TYPE_ECHO_REPLY, (short) 0);
500 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMPV6, replyMatchInfo,
501 AclConstants.ICMPV6_TYPE_ECHO_REPLY, addOrRemove);
506 private void programIcmpFlow(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
507 AllowedAddressPairs allowedAddress, MatchIpProtocol protocol, MatchInfo icmpTypeMatchInfo,
508 int icmpType, int addOrRemove) {
509 List<MatchInfoBase> matches = new ArrayList<>();
510 matches.add(protocol);
511 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
512 matches.add(new MatchEthernetDestination(allowedAddress.getMacAddress()));
513 matches.addAll(AclServiceUtils.buildIpMatches(allowedAddress.getIpAddress(), MatchCriteria.MATCH_DESTINATION));
514 matches.add(icmpTypeMatchInfo);
516 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
517 String flowName = "Ingress_DHCP_Service_ICMP_" + dpId + "_" + lportTag + "_" + icmpType + "_Permit_";
518 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
519 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
520 instructions, addOrRemove);
524 * Add rule to drop BUM traffic to DHCP Server.
526 * @param flowEntries the flow entries
527 * @param dpId the dpid
528 * @param lportTag the lport tag
529 * @param addOrRemove is write or delete
531 protected void dropTrafficToDhcpServer(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
533 InstructionInfo writeMetatdata = AclServiceUtils.getWriteMetadataForDropFlag();
534 List<InstructionInfo> instructions = Lists.newArrayList(writeMetatdata);
535 instructions.addAll(AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable()));
537 List<MatchInfoBase> matches = new ArrayList<>();
538 matches.add(new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
539 MetaDataUtil.getLportTagMaskForReg6()));
541 String flowName = "Ingress_DHCP_Service_" + dpId + "_" + lportTag + "_Drop";
542 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
543 AclConstants.PROTO_DHCP_SERVER_DROP_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
544 instructions, addOrRemove);
548 protected boolean isValidDirection(Class<? extends DirectionBase> direction) {
549 return direction.equals(DirectionIngress.class);
552 private short getAclAntiSpoofingTable() {
553 return NwConstants.EGRESS_ACL_ANTI_SPOOFING_TABLE;
556 private short getAclConntrackClassifierTable() {
557 return NwConstants.EGRESS_ACL_CONNTRACK_CLASSIFIER_TABLE;
561 protected short getAclConntrackSenderTable() {
562 return NwConstants.EGRESS_ACL_CONNTRACK_SENDER_TABLE;
566 protected short getAclForExistingTrafficTable() {
567 return NwConstants.EGRESS_ACL_FOR_EXISTING_TRAFFIC_TABLE;
571 protected short getAclFilterCumDispatcherTable() {
572 return NwConstants.EGRESS_ACL_FILTER_CUM_DISPATCHER_TABLE;
576 protected short getAclRuleBasedFilterTable() {
577 return NwConstants.EGRESS_ACL_RULE_BASED_FILTER_TABLE;
581 protected short getAclRemoteAclTable() {
582 return NwConstants.EGRESS_REMOTE_ACL_TABLE;
586 protected short getAclCommitterTable() {
587 return NwConstants.EGRESS_ACL_COMMITTER_TABLE;