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.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.genius.mdsalutil.FlowEntity;
20 import org.opendaylight.genius.mdsalutil.InstructionInfo;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.genius.mdsalutil.MatchInfo;
23 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
24 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
25 import org.opendaylight.genius.mdsalutil.NwConstants;
26 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
27 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
28 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
29 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
30 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv4;
31 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
32 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
33 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
34 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
35 import org.opendaylight.genius.utils.ServiceIndex;
36 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
37 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
38 import org.opendaylight.netvirt.aclservice.api.AclServiceManager;
39 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
40 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
41 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
42 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
43 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
44 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
45 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl.InterfaceType;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.opendaylight.yangtools.yang.common.Uint64;
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, serviceMode);
113 return Collections.singletonList(
114 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.put(
115 path, serviceInfo, CREATE_MISSING_PARENTS)));
122 * @param aclInterface the acl interface
125 protected void unbindService(AclInterface aclInterface) {
126 String interfaceName = aclInterface.getInterfaceId();
127 InstanceIdentifier<BoundServices> path = AclServiceUtils.buildServiceId(interfaceName,
128 ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX),
131 LOG.debug("UnBinding ACL service for interface {}", interfaceName);
132 jobCoordinator.enqueueJob(interfaceName, () -> Collections.singletonList(txRunner
133 .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path))));
137 * Programs DHCP Service flows.
139 * @param flowEntries the flow entries
140 * @param port the acl interface
141 * @param action add/modify/remove action
142 * @param addOrRemove addorRemove
145 protected void programDhcpService(List<FlowEntity> flowEntries, AclInterface port,
146 Action action, int addOrRemove) {
147 LOG.info("{} programDhcpService for port {}, action={}, addOrRemove={}", this.directionString,
148 port.getInterfaceId(), action, addOrRemove);
149 Uint64 dpid = Uint64.valueOf(port.getDpId());
150 int lportTag = port.getLPortTag();
151 allowDhcpClientTraffic(flowEntries, dpid, lportTag, addOrRemove);
152 allowDhcpv6ClientTraffic(flowEntries, dpid, lportTag, addOrRemove);
153 programArpRule(flowEntries, dpid, lportTag, addOrRemove);
154 ingressAclIcmpv6AllowedTraffic(flowEntries, port, InterfaceType.DhcpService, addOrRemove);
155 allowIcmpTrafficToDhcpServer(flowEntries, port, port.getAllowedAddressPairs(), addOrRemove);
156 dropTrafficToDhcpServer(flowEntries, dpid, lportTag, addOrRemove);
157 programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
161 * Programs DHCP service flows.
163 * @param flowEntries the flow entries
164 * @param port the acl interface
165 * @param allowedAddresses the allowed addresses
166 * @param addOrRemove addorRemove
169 protected void processDhcpServiceUpdate(List<FlowEntity> flowEntries, AclInterface port,
170 List<AllowedAddressPairs> allowedAddresses, int addOrRemove) {
171 allowIcmpTrafficToDhcpServer(flowEntries, port, allowedAddresses, addOrRemove);
175 protected void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
176 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
177 LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
178 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
180 Uint64 dpid = Uint64.valueOf(port.getDpId());
181 int lportTag = port.getLPortTag();
182 if (action == Action.ADD || action == Action.REMOVE) {
183 programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
184 ingressAclDhcpAllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
185 ingressAclDhcpv6AllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
186 ingressAclIcmpv6AllowedTraffic(flowEntries, port, InterfaceType.AccessPort, addOrRemove);
187 programIcmpv6RARule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
189 programArpRule(flowEntries, dpid, lportTag, addOrRemove);
190 programIpv4BroadcastRule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
194 private void programCommitterDropFlow(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
196 List<MatchInfoBase> matches = new ArrayList<>();
197 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
199 Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_ACL_DROP.longValue()
200 & (AclConstants.METADATA_DROP_FLAG.longValue() << 2));
201 Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_ACL_DROP.longValue()
202 & (AclConstants.METADATA_DROP_FLAG.longValue() << 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, Uint64 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 + "_"
230 + mac.getValue() + "_" + 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, Uint64 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, Uint64 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, Uint64 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 Uint64 dpId = Uint64.valueOf(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)) {
341 Uint64 dpid = Uint64.valueOf(port.getDpId());
342 /* Allow ICMPv6 Router Advertisement packets from external routers as well as internal routers
343 * if subnet is configured with IPv6 version
344 * Allow ICMPv6 Router Advertisement packets if originating from any LinkLocal Address.
346 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
347 List<MatchInfoBase> matches =
348 AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_RA, 0,
349 port.getLPortTag(), serviceMode);
350 matches.addAll(AclServiceUtils.buildIpMatches(
351 new IpPrefixOrAddress(IpPrefixBuilder.getDefaultInstance(AclConstants.IPV6_LINK_LOCAL_PREFIX)),
352 AclServiceManager.MatchCriteria.MATCH_SOURCE));
353 String flowName = "Ingress_ICMPv6" + "_" + dpid + "_" + port.getLPortTag() + "_"
354 + AclConstants.ICMPV6_TYPE_RA + "_LinkLocal_Permit_";
355 addFlowEntryToList(flowEntries, dpid, getAclAntiSpoofingTable(), flowName,
356 AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
357 instructions, addOrRemove);
361 * Adds the rule to allow arp packets.
363 * @param flowEntries the flow entries
364 * @param dpId the dpId
365 * @param lportTag the lport tag
366 * @param addOrRemove whether to add or remove the flow
368 protected void programArpRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag, int addOrRemove) {
369 List<MatchInfoBase> matches = new ArrayList<>();
370 matches.add(MatchEthernetType.ARP);
371 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
372 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
373 LOG.debug("{} ARP Rule on DPID {}, lportTag {}", addOrRemove == NwConstants.DEL_FLOW ? "Deleting" : "Adding",
375 String flowName = "Ingress_ARP_" + dpId + "_" + lportTag;
376 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
377 AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
378 instructions, addOrRemove);
383 * Programs broadcast rules.
385 * @param flowEntries the flow entries
386 * @param port the Acl Interface port
387 * @param addOrRemove whether to delete or add flow
390 protected void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, Action action,
392 programIpv4BroadcastRule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
396 * Programs broadcast rules.
398 * @param flowEntries the flow entries
399 * @param port the Acl Interface port
400 * @param subnetInfoList the port subnet info list
401 * @param addOrRemove whether to delete or add flow
403 protected void programSubnetBroadcastRules(List<FlowEntity> flowEntries, AclInterface port,
404 List<SubnetInfo> subnetInfoList, int addOrRemove) {
405 programIpv4BroadcastRule(flowEntries, port, subnetInfoList, addOrRemove);
409 * Programs IPv4 broadcast rules.
411 * @param flowEntries the flow entries
412 * @param port the Acl Interface port
413 * @param subnetInfoList Port subnet list
414 * @param addOrRemove whether to delete or add flow
416 private void programIpv4BroadcastRule(List<FlowEntity> flowEntries, AclInterface port,
417 List<SubnetInfo> subnetInfoList, int addOrRemove) {
418 Uint64 dpId = Uint64.valueOf(port.getDpId());
419 int lportTag = port.getLPortTag();
420 MatchInfoBase lportMatchInfo = AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode);
421 if (subnetInfoList != null) {
422 List<String> broadcastAddresses = AclServiceUtils.getIpBroadcastAddresses(subnetInfoList);
423 for (String broadcastAddress : broadcastAddresses) {
424 List<MatchInfoBase> matches =
425 AclServiceUtils.buildBroadcastIpV4Matches(broadcastAddress);
426 matches.add(lportMatchInfo);
427 List<InstructionInfo> instructions = new ArrayList<>();
428 instructions.add(new InstructionGotoTable(getAclConntrackClassifierTable()));
429 String flowName = "Ingress_v4_Broadcast_" + dpId + "_"
430 + lportTag + "_" + broadcastAddress + "_Permit";
431 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
432 AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
436 LOG.warn("IP Broadcast CIDRs are missing for port {}", port.getInterfaceId());
441 * Add rule to ensure only DHCP client traffic is allowed.
443 * @param flowEntries the flow entries
444 * @param dpId the dpid
445 * @param lportTag the lport tag
446 * @param addOrRemove is write or delete
448 protected void allowDhcpClientTraffic(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
450 final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_CLIENT_PORT_IPV4,
451 AclConstants.DHCP_SERVER_PORT_IPV4, lportTag, serviceMode);
452 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
454 String flowName = "Ingress_DHCP_Service_v4" + dpId + "_" + lportTag + "_Permit_";
455 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
456 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
457 instructions, addOrRemove);
461 * Add rule to ensure only DHCPv6 client traffic is allowed.
463 * @param flowEntries the flow entries
464 * @param dpId the dpid
465 * @param lportTag the lport tag
466 * @param addOrRemove is write or delete
468 protected void allowDhcpv6ClientTraffic(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
470 final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_CLIENT_PORT_IPV6,
471 AclConstants.DHCP_SERVER_PORT_IPV6, lportTag, serviceMode);
472 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
474 String flowName = "Ingress_DHCP_Service_v6" + "_" + dpId + "_" + lportTag + "_Permit_";
475 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
476 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
477 instructions, addOrRemove);
481 * Add rules to allow ICMP traffic for DHCP server.
482 * @param flowEntries the flow entries
483 * @param port the Acl Interface port
484 * @param allowedAddresses the allowed addresses
485 * @param addOrRemove the lport tag
487 protected void allowIcmpTrafficToDhcpServer(List<FlowEntity> flowEntries, AclInterface port,
488 List<AllowedAddressPairs> allowedAddresses, int addOrRemove) {
489 Uint64 dpId = Uint64.valueOf(port.getDpId());
490 int lportTag = port.getLPortTag();
491 for (AllowedAddressPairs allowedAddress : allowedAddresses) {
492 if (AclServiceUtils.isIPv4Address(allowedAddress)) {
493 MatchInfo reqMatchInfo = new MatchIcmpv4((short) AclConstants.ICMPV4_TYPE_ECHO_REQUEST, (short) 0);
494 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMP, reqMatchInfo,
495 AclConstants.ICMPV4_TYPE_ECHO_REQUEST, addOrRemove);
496 MatchInfo replyMatchInfo = new MatchIcmpv4((short) AclConstants.ICMPV4_TYPE_ECHO_REPLY, (short) 0);
497 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMP, replyMatchInfo,
498 AclConstants.ICMPV4_TYPE_ECHO_REPLY, addOrRemove);
500 MatchInfo reqMatchInfo = new MatchIcmpv6((short) AclConstants.ICMPV6_TYPE_ECHO_REQUEST, (short) 0);
501 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMPV6, reqMatchInfo,
502 AclConstants.ICMPV6_TYPE_ECHO_REQUEST, addOrRemove);
503 MatchInfo replyMatchInfo = new MatchIcmpv6((short) AclConstants.ICMPV6_TYPE_ECHO_REPLY, (short) 0);
504 programIcmpFlow(flowEntries, dpId, lportTag, allowedAddress, MatchIpProtocol.ICMPV6, replyMatchInfo,
505 AclConstants.ICMPV6_TYPE_ECHO_REPLY, addOrRemove);
510 private void programIcmpFlow(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
511 AllowedAddressPairs allowedAddress, MatchIpProtocol protocol, MatchInfo icmpTypeMatchInfo,
512 int icmpType, int addOrRemove) {
513 List<MatchInfoBase> matches = new ArrayList<>();
514 matches.add(protocol);
515 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
516 matches.add(new MatchEthernetDestination(allowedAddress.getMacAddress()));
517 matches.addAll(AclServiceUtils.buildIpMatches(allowedAddress.getIpAddress(), MatchCriteria.MATCH_DESTINATION));
518 matches.add(icmpTypeMatchInfo);
520 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
521 String flowName = "Ingress_DHCP_Service_ICMP_" + dpId + "_" + lportTag + "_" + icmpType + "_Permit_";
522 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
523 AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
524 instructions, addOrRemove);
528 * Add rule to drop BUM traffic to DHCP Server.
530 * @param flowEntries the flow entries
531 * @param dpId the dpid
532 * @param lportTag the lport tag
533 * @param addOrRemove is write or delete
535 protected void dropTrafficToDhcpServer(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
537 InstructionInfo writeMetatdata = AclServiceUtils.getWriteMetadataForDropFlag();
538 List<InstructionInfo> instructions = Lists.newArrayList(writeMetatdata);
539 instructions.addAll(AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable()));
541 List<MatchInfoBase> matches = new ArrayList<>();
542 matches.add(new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
543 MetaDataUtil.getLportTagMaskForReg6()));
545 String flowName = "Ingress_DHCP_Service_" + dpId + "_" + lportTag + "_Drop";
546 addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
547 AclConstants.PROTO_DHCP_SERVER_DROP_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
548 instructions, addOrRemove);
552 protected boolean isValidDirection(Class<? extends DirectionBase> direction) {
553 return direction.equals(DirectionIngress.class);
556 private short getAclAntiSpoofingTable() {
557 return NwConstants.EGRESS_ACL_ANTI_SPOOFING_TABLE;
560 private short getAclConntrackClassifierTable() {
561 return NwConstants.EGRESS_ACL_CONNTRACK_CLASSIFIER_TABLE;
565 protected short getAclConntrackSenderTable() {
566 return NwConstants.EGRESS_ACL_CONNTRACK_SENDER_TABLE;
570 protected short getAclForExistingTrafficTable() {
571 return NwConstants.EGRESS_ACL_FOR_EXISTING_TRAFFIC_TABLE;
575 protected short getAclFilterCumDispatcherTable() {
576 return NwConstants.EGRESS_ACL_FILTER_CUM_DISPATCHER_TABLE;
580 protected short getAclRuleBasedFilterTable() {
581 return NwConstants.EGRESS_ACL_RULE_BASED_FILTER_TABLE;
585 protected short getAclRemoteAclTable() {
586 return NwConstants.EGRESS_REMOTE_ACL_TABLE;
590 protected short getAclCommitterTable() {
591 return NwConstants.EGRESS_ACL_COMMITTER_TABLE;