2 * Copyright (c) 2016 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 java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
14 import java.util.stream.Collectors;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.genius.mdsalutil.ActionInfo;
17 import org.opendaylight.genius.mdsalutil.InstructionInfo;
18 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
21 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
22 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
23 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
24 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetSource;
25 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
26 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
27 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
28 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
29 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
30 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
31 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
32 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
33 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
34 import org.opendaylight.netvirt.aclservice.utils.StatefulAclServiceHelper;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 * Provides the stateful implementation for egress (w.r.t VM) ACL service.
50 * Note: Table names used are w.r.t switch. Hence, switch ingress is VM egress
54 public class StatefulEgressAclServiceImpl extends AbstractEgressAclServiceImpl {
56 private static final Logger LOG = LoggerFactory.getLogger(StatefulEgressAclServiceImpl.class);
58 public StatefulEgressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil,
59 AclServiceUtils aclServiceUtils, JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
60 super(dataBroker, mdsalManager, aclDataUtil, aclServiceUtils, jobCoordinator, aclInterfaceCache);
64 * Program conntrack rules.
66 * @param dpid the dpid
67 * @param dhcpMacAddress the dhcp mac address.
68 * @param allowedAddresses the allowed addresses
69 * @param lportTag the lport tag
70 * @param addOrRemove addorRemove
73 protected void programSpecificFixedRules(BigInteger dpid, String dhcpMacAddress,
74 List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int addOrRemove) {
75 programEgressAclFixedConntrackRule(dpid, allowedAddresses, lportTag, portId, action, addOrRemove);
79 protected String syncSpecificAclFlow(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId,
80 Map<String, List<MatchInfoBase>> flowMap, String flowName) {
82 Long elanId = getElanIdFromAclInterface(portId);
83 List<ActionInfo> actionsInfos = new ArrayList<>();
84 List<InstructionInfo> instructions;
85 PacketHandling packetHandling = ace.getActions() != null ? ace.getActions().getPacketHandling() : null;
86 if (packetHandling instanceof Permit) {
87 List<NxCtAction> ctActionsList = new ArrayList<>();
88 NxCtAction nxCtMarkSetAction = new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE);
89 ctActionsList.add(nxCtMarkSetAction);
91 ActionNxConntrack actionNxConntrack = new ActionNxConntrack(2, 1, 0, elanId.intValue(),
92 (short) 255, ctActionsList);
93 actionsInfos.add(actionNxConntrack);
94 instructions = getDispatcherTableResubmitInstructions(actionsInfos);
96 instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
98 List<MatchInfoBase> matches = flowMap.get(flowName);
99 matches.add(buildLPortTagMatch(lportTag));
100 matches.add(new NxMatchCtState(AclConstants.TRACKED_CT_STATE, AclConstants.TRACKED_CT_STATE_MASK));
101 AceIp acl = (AceIp) ace.getMatches().getAceType();
102 final String applyChangeOnExistingTrafficFlowName = flowName + "Egress" + lportTag
103 + ((acl.getAceIpVersion() instanceof AceIpv4) ? "_IPv4" : "_IPv6") + "_FlowAfterRuleDeleted";
104 flowName += "Egress" + lportTag + ace.getKey().getRuleName();
105 String poolName = AclServiceUtils.getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, packetHandling);
106 // For flows related remote ACL, unique flow priority is used for
107 // each flow to avoid overlapping flows
108 int priority = getAclFlowPriority(poolName, flowName, addOrRemove);
110 syncFlow(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, flowName, priority, "ACL", 0, 0,
111 AclConstants.COOKIE_ACL_BASE, matches, instructions,
112 (addOrRemove == NwConstants.MOD_FLOW) ? NwConstants.DEL_FLOW : addOrRemove);
114 if (addOrRemove != NwConstants.DEL_FLOW) {
115 final List<MatchInfoBase> applyChangeOnExistingTrafficFlowMatches = matches.stream()
116 .filter(obj -> !(obj instanceof NxMatchCtState))
117 .collect(Collectors.toList());
118 applyChangeOnExistingTrafficFlowMatches.add(new NxMatchCtState(AclConstants.TRACKED_RPL_CT_STATE,
119 AclConstants.TRACKED_RPL_CT_STATE_MASK));
121 instructions = StatefulAclServiceHelper.createCtMarkInstructionForNewState(getEgressAclFilterTable(),
123 syncFlow(dpId, NwConstants.INGRESS_ACL_STATEFUL_APPLY_CHANGE_EXIST_TRAFFIC_TABLE,
124 applyChangeOnExistingTrafficFlowName, priority, "ACL",
125 0, StatefulAclServiceHelper.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils),
126 AclConstants.COOKIE_ACL_BASE, applyChangeOnExistingTrafficFlowMatches,
127 instructions, (addOrRemove == NwConstants.ADD_FLOW) ? 1 : 0);
134 * Adds the rule to send the packet to the netfilter to check whether it is
137 * @param dpId the dpId
138 * @param allowedAddresses the allowed addresses
139 * @param priority the priority of the flow
140 * @param flowId the flowId
141 * @param conntrackState the conntrack state of the packets thats should be
143 * @param conntrackMask the conntrack mask
144 * @param portId the portId
145 * @param addOrRemove whether to add or remove the flow
147 private void programConntrackRecircRules(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
148 Integer priority, String flowId, String portId, int addOrRemove) {
149 for (AllowedAddressPairs allowedAddress : allowedAddresses) {
150 IpPrefixOrAddress attachIp = allowedAddress.getIpAddress();
151 MacAddress attachMac = allowedAddress.getMacAddress();
153 List<MatchInfoBase> matches = new ArrayList<>();
154 matches.add(new MatchEthernetSource(attachMac));
155 matches.addAll(AclServiceUtils.buildIpMatches(attachIp, MatchCriteria.MATCH_SOURCE));
157 Long elanTag = getElanIdFromAclInterface(portId);
158 List<InstructionInfo> instructions = new ArrayList<>();
159 List<ActionInfo> actionsInfos = new ArrayList<>();
160 actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(),
161 NwConstants.INGRESS_ACL_REMOTE_ACL_TABLE));
162 instructions.add(new InstructionApplyActions(actionsInfos));
164 String flowName = "Egress_Fixed_Conntrk_" + dpId + "_" + attachMac.getValue() + "_"
165 + String.valueOf(attachIp.getValue()) + "_" + flowId;
166 syncFlow(dpId, NwConstants.INGRESS_ACL_TABLE, flowName, AclConstants.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
167 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
172 * Programs the default connection tracking rules.
174 * @param dpid the dp id
175 * @param allowedAddresses the allowed addresses
176 * @param lportTag the lport tag
177 * @param portId the portId
178 * @param action the action
179 * @param write whether to add or remove the flow.
181 private void programEgressAclFixedConntrackRule(BigInteger dpid, List<AllowedAddressPairs> allowedAddresses,
182 int lportTag, String portId, Action action, int write) {
183 programConntrackRecircRules(dpid, allowedAddresses, AclConstants.CT_STATE_UNTRACKED_PRIORITY,
184 "Recirc", portId, write);
185 programEgressConntrackDropRules(dpid, lportTag, write);
186 LOG.info("programEgressAclFixedConntrackRule : default connection tracking rule are {} on DpId {}"
187 + "lportTag {}.", write == NwConstants.ADD_FLOW ? "added" : "removed", dpid, lportTag);
191 * Adds the rule to drop the unknown/invalid packets .
193 * @param dpId the dpId
194 * @param lportTag the lport tag
195 * @param priority the priority of the flow
196 * @param flowId the flowId
197 * @param conntrackState the conntrack state of the packets thats should be
199 * @param conntrackMask the conntrack mask
200 * @param tableId table id
201 * @param addOrRemove whether to add or remove the flow
203 private void programConntrackDropRule(BigInteger dpId, int lportTag, Integer priority, String flowId,
204 int conntrackState, int conntrackMask, int addOrRemove) {
205 List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag, conntrackState,
206 conntrackMask, ServiceModeEgress.class);
207 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
209 flowId = "Ingress_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_" + flowId;
210 syncFlow(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, flowId, priority, "ACL", 0, 0,
211 AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
215 * Adds the rules to drop the unknown/invalid packets .
217 * @param dpId the dpId
218 * @param lportTag the lport tag
219 * @param addOrRemove whether to add or remove the flow
221 private void programEgressConntrackDropRules(BigInteger dpId, int lportTag, int addOrRemove) {
222 LOG.debug("Applying Egress ConnTrack Drop Rules on DpId {}, lportTag {}", dpId, lportTag);
223 programConntrackDropRule(dpId, lportTag, AclConstants.CT_STATE_TRACKED_NEW_DROP_PRIORITY, "Tracked_New",
224 AclConstants.TRACKED_CT_STATE, AclConstants.TRACKED_CT_STATE_MASK, addOrRemove);
225 programConntrackDropRule(dpId, lportTag, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, "Tracked_Invalid",
226 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, addOrRemove);