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;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.genius.mdsalutil.ActionInfo;
15 import org.opendaylight.genius.mdsalutil.ActionType;
16 import org.opendaylight.genius.mdsalutil.FlowEntity;
17 import org.opendaylight.genius.mdsalutil.InstructionInfo;
18 import org.opendaylight.genius.mdsalutil.InstructionType;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
21 import org.opendaylight.genius.mdsalutil.NwConstants;
22 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
23 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
24 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
25 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 public abstract class AbstractAclServiceImpl implements AclServiceListener {
38 private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
40 private final IMdsalApiManager mdsalManager;
41 private final OdlInterfaceRpcService interfaceManager;
42 private final DataBroker dataBroker;
43 private final Class<? extends ServiceModeBase> serviceMode;
46 * Initialize the member variables.
48 * @param serviceMode the service mode
49 * @param dataBroker the data broker instance.
50 * @param interfaceManager the interface manager instance.
51 * @param mdsalManager the mdsal manager instance.
53 public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
54 OdlInterfaceRpcService interfaceManager, IMdsalApiManager mdsalManager) {
55 this.dataBroker = dataBroker;
56 this.interfaceManager = interfaceManager;
57 this.mdsalManager = mdsalManager;
58 this.serviceMode = serviceMode;
62 public boolean applyAcl(Interface port) {
64 if (!AclServiceUtils.isPortSecurityEnabled(port)) {
68 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
69 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
70 BigInteger dpId = AclServiceUtils.getDpIdFromIterfaceState(interfaceState);
72 LOG.error("Unable to find DP Id from interface state {}", interfaceState.getName());
76 programAclWithAllowedAddress(dpId, AclServiceUtils.getPortAllowedAddresses(port), interfaceState.getIfIndex(),
77 AclServiceUtils.getInterfaceAcls(port), NwConstants.ADD_FLOW);
79 // TODO: uncomment bindservice() when the acl flow programming is
81 // bindService(port.getName());
86 public boolean updateAcl(Interface portBefore, Interface portAfter) {
87 boolean result = false;
88 boolean isPortSecurityEnable = AclServiceUtils.isPortSecurityEnabled(portAfter);
89 boolean isPortSecurityEnableBefore = AclServiceUtils.isPortSecurityEnabled(portBefore);
90 // if port security is changed, apply/remove Acls
91 if (isPortSecurityEnableBefore != isPortSecurityEnable) {
92 if (isPortSecurityEnable) {
93 result = applyAcl(portAfter);
95 result = removeAcl(portAfter);
97 } else if (isPortSecurityEnable) {
98 // Acls has been updated, find added/removed Acls and act accordingly.
99 this.processInterfaceUpdate(portBefore, portAfter);
105 private void processInterfaceUpdate(Interface portBefore, Interface portAfter) {
106 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
107 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, portAfter.getName());
108 BigInteger dpId = AclServiceUtils.getDpIdFromIterfaceState(interfaceState);
109 List<AllowedAddressPairs> addedAllowedAddressPairs =
110 AclServiceUtils.getUpdatedAllowedAddressPairs(portAfter,portBefore);
111 List<AllowedAddressPairs> deletedAllowedAddressPairs =
112 AclServiceUtils.getUpdatedAllowedAddressPairs(portBefore, portAfter);
113 if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
114 programAclWithAllowedAddress(dpId, addedAllowedAddressPairs, interfaceState.getIfIndex(),
115 AclServiceUtils.getInterfaceAcls(portAfter), NwConstants.ADD_FLOW);
117 if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
118 programAclWithAllowedAddress(dpId, deletedAllowedAddressPairs, interfaceState.getIfIndex(),
119 AclServiceUtils.getInterfaceAcls(portAfter), NwConstants.DEL_FLOW);
122 List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter, portBefore);
123 List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore, portAfter);
124 if (addedAcls != null && !addedAcls.isEmpty()) {
125 updateCustomRules(dpId, interfaceState.getIfIndex(), addedAcls, NwConstants.ADD_FLOW);
127 if (deletedAcls != null && !deletedAcls.isEmpty()) {
128 updateCustomRules(dpId, interfaceState.getIfIndex(), deletedAcls, NwConstants.DEL_FLOW);
132 private void updateCustomRules(BigInteger dpId, int lportTag, List<Uuid> aclUuidList, int action) {
133 programAclRules(aclUuidList, dpId, lportTag, action);
136 private void programAclWithAllowedAddress(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
137 int lportTag, List<Uuid> aclUuidList, int addOrRemove) {
138 programFixedRules(dpId, "", allowedAddresses, lportTag, addOrRemove);
139 programAclRules(aclUuidList, dpId, lportTag, addOrRemove);
143 public boolean removeAcl(Interface port) {
144 if (!AclServiceUtils.isPortSecurityEnabled(port)) {
147 BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
148 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
149 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
150 programAclWithAllowedAddress(dpId, AclServiceUtils.getPortAllowedAddresses(port), interfaceState.getIfIndex(),
151 AclServiceUtils.getInterfaceAcls(port), NwConstants.DEL_FLOW);
153 // TODO: uncomment unbindService() when the acl flow programming is
155 // unbindService(port.getName());
160 public boolean applyAce(Interface port, Ace ace) {
161 if (!AclServiceUtils.isPortSecurityEnabled(port)) {
164 BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
165 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
166 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
167 programAceRule(dpId, interfaceState.getIfIndex(), NwConstants.ADD_FLOW, ace);
172 public boolean removeAce(Interface port, Ace ace) {
173 if (!AclServiceUtils.isPortSecurityEnabled(port)) {
176 BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
177 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
178 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
179 programAceRule(dpId, interfaceState.getIfIndex(), NwConstants.DEL_FLOW, ace);
187 * @param interfaceName the interface name
189 protected abstract void bindService(String interfaceName);
194 * @param interfaceName the interface name
196 protected abstract void unbindService(String interfaceName);
199 * Program the default anti-spoofing rule and the conntrack rules.
201 * @param dpid the dpid
202 * @param dhcpMacAddress the dhcp mac address.
203 * @param allowedAddresses the allowed addresses
204 * @param lportTag the lport tag
205 * @param addOrRemove addorRemove
207 protected abstract void programFixedRules(BigInteger dpid, String dhcpMacAddress,
208 List<AllowedAddressPairs> allowedAddresses, int lportTag, int addOrRemove);
211 * Programs the acl custom rules.
213 * @param aclUuidList the list of acl uuid to be applied
214 * @param dpId the dpId
215 * @param lportTag the lport tag
216 * @param addOrRemove whether to delete or add flow
218 protected abstract void programAclRules(List<Uuid> aclUuidList, BigInteger dpId, int lportTag, int addOrRemove);
221 * Programs the ace custom rule.
223 * @param dpId the dpId
224 * @param lportTag the lport tag
225 * @param addOrRemove whether to delete or add flow
226 * @param ace rule to be program
228 protected abstract void programAceRule(BigInteger dpId, int lportTag, int addOrRemove, Ace ace);
231 * Writes/remove the flow to/from the datastore.
232 * @param dpId the dpId
233 * @param tableId the tableId
234 * @param flowId the flowId
235 * @param priority the priority
236 * @param flowName the flow name
237 * @param idleTimeOut the idle timeout
238 * @param hardTimeOut the hard timeout
239 * @param cookie the cookie
240 * @param matches the list of matches to be writted
241 * @param instructions the list of instruction to be written.
242 * @param addOrRemove add or remove the entries.
244 protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
245 int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
246 List<InstructionInfo> instructions, int addOrRemove) {
247 if (addOrRemove == NwConstants.DEL_FLOW) {
248 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,flowId,
249 priority, flowName , idleTimeOut, hardTimeOut, cookie, matches, null);
250 LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
251 mdsalManager.removeFlow(flowEntity);
253 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId,
254 priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions);
255 LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
256 mdsalManager.installFlow(flowEntity);
261 * Gets the dispatcher table resubmit instructions based on ingress/egress
262 * service mode w.r.t switch.
264 * @param actionsInfos the actions infos
265 * @return the instructions for dispatcher table resubmit
267 protected List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos) {
268 short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
269 if (ServiceModeEgress.class.equals(this.serviceMode)) {
270 dispatcherTableId = AclConstants.EGRESS_LPORT_DISPATCHER_TABLE;
273 List<InstructionInfo> instructions = new ArrayList<>();
274 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
275 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));