Merge "Fix for SingleFeatureTest wiring for neutron model"
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / AbstractAclServiceImpl.java
1 /*
2  * Copyright (c) 2016 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 java.math.BigInteger;
11 import java.util.List;
12
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.genius.mdsalutil.FlowEntity;
15 import org.opendaylight.genius.mdsalutil.InstructionInfo;
16 import org.opendaylight.genius.mdsalutil.MDSALUtil;
17 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
20 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
21 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 public abstract class AbstractAclServiceImpl implements AclServiceListener {
30
31     private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
32
33     private final IMdsalApiManager mdsalManager;
34     private final OdlInterfaceRpcService interfaceManager;
35     private final DataBroker dataBroker;
36
37     /**
38      * Initialize the member variables.
39      * @param dataBroker the data broker instance.
40      * @param interfaceManager the interface manager instance.
41      * @param mdsalManager the mdsal manager instance.
42      */
43     public AbstractAclServiceImpl(DataBroker dataBroker, OdlInterfaceRpcService interfaceManager,
44                                   IMdsalApiManager mdsalManager) {
45         this.dataBroker = dataBroker;
46         this.interfaceManager = interfaceManager;
47         this.mdsalManager = mdsalManager;
48     }
49
50     @Override
51     public boolean applyAcl(Interface port) {
52
53         if (!AclServiceUtils.isPortSecurityEnabled(port)) {
54             return false;
55         }
56         BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
57         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
58             interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
59         String attachMac = interfaceState.getPhysAddress().getValue();
60         programFixedRules(dpId, "", attachMac, NwConstants.ADD_FLOW);
61         List<Uuid> aclUuidList = AclServiceUtils.getInterfaceAcls(port);
62         programAclRules(aclUuidList, dpId, attachMac,NwConstants.ADD_FLOW );
63         // TODO: uncomment bindservice() when the acl flow programming is
64         // implemented
65         // bindService(port.getName());
66         return true;
67     }
68
69     @Override
70     public boolean updateAcl(Interface portBefore, Interface portAfter) {
71         boolean result = false;
72         boolean isPortSecurityEnable = AclServiceUtils.isPortSecurityEnabled(portAfter);
73         boolean isPortSecurityEnableBefore = AclServiceUtils.isPortSecurityEnabled(portBefore);
74         // if port security is changed, apply/remove Acls
75         if (isPortSecurityEnableBefore != isPortSecurityEnable) {
76             if (isPortSecurityEnable) {
77                 result = applyAcl(portAfter);
78             } else {
79                 result = removeAcl(portAfter);
80             }
81         } else if (isPortSecurityEnable) {
82             // Acls has been updated, find added/removed Acls and act accordingly.
83             this.processInterfaceUpdate(portBefore, portAfter);
84         }
85
86         return result;
87     }
88
89     private void processInterfaceUpdate(Interface portBefore, Interface portAfter) {
90         List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter, portBefore);
91         List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore, portAfter);
92         if (addedAcls != null && !addedAcls.isEmpty()) {
93             updateCustomRules(portAfter, addedAcls, NwConstants.ADD_FLOW);
94         }
95         if (deletedAcls != null && !deletedAcls.isEmpty()) {
96             updateCustomRules(portAfter, deletedAcls, NwConstants.DEL_FLOW);
97         }
98     }
99
100     private void updateCustomRules(Interface portAfter, List<Uuid> aclUuidList, int action) {
101         BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, portAfter.getName());
102         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
103                 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, portAfter.getName());
104         String attachMac = interfaceState.getPhysAddress().getValue();
105         programAclRules(aclUuidList, dpId, attachMac, action);
106     }
107
108     @Override
109     public boolean removeAcl(Interface port) {
110         if (!AclServiceUtils.isPortSecurityEnabled(port)) {
111             return false;
112         }
113         BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
114         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
115             interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
116         String attachMac = interfaceState.getPhysAddress().getValue();
117         programFixedRules(dpId, "", attachMac, NwConstants.DEL_FLOW);
118         List<Uuid> aclUuidList = AclServiceUtils.getInterfaceAcls(port);
119         programAclRules(aclUuidList, dpId, attachMac,NwConstants.DEL_FLOW );
120
121         // TODO: uncomment unbindService() when the acl flow programming is
122         // implemented
123         // unbindService(port.getName());
124         return true;
125     }
126
127     @Override
128     public boolean applyAce(Interface port, Ace ace) {
129         if (!AclServiceUtils.isPortSecurityEnabled(port)) {
130             return false;
131         }
132         BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
133         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
134                 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
135         String attachMac = interfaceState.getPhysAddress().getValue();
136         programAceRule(dpId, attachMac, NwConstants.ADD_FLOW, ace);
137         return true;
138     }
139
140     @Override
141     public boolean removeAce(Interface port, Ace ace) {
142         if (!AclServiceUtils.isPortSecurityEnabled(port)) {
143             return false;
144         }
145         BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
146         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
147                 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
148         String attachMac = interfaceState.getPhysAddress().getValue();
149         programAceRule(dpId, attachMac, NwConstants.DEL_FLOW, ace);
150         return true;
151     }
152
153
154     /**
155      * Bind service.
156      *
157      * @param interfaceName the interface name
158      */
159     protected abstract void bindService(String interfaceName);
160
161     /**
162      * Unbind service.
163      *
164      * @param interfaceName the interface name
165      */
166     protected abstract void unbindService(String interfaceName);
167
168     /**
169      * Program the default anti-spoofing rule and the conntrack rules.
170      *
171      * @param dpid the dpid
172      * @param dhcpMacAddress the dhcp mac address.
173      * @param attachMac The vm mac address
174      * @param addOrRemove addorRemove
175      */
176     protected abstract void programFixedRules(BigInteger dpid, String dhcpMacAddress,
177                                            String attachMac, int addOrRemove);
178
179     /**
180      * Programs the acl custom rules.
181      *
182      * @param aclUuidList the list of acl uuid to be applied
183      * @param dpId the dpId
184      * @param attachMac the attached mac
185      * @param addOrRemove whether to delete or add flow
186      */
187     protected abstract void programAclRules(List<Uuid> aclUuidList, BigInteger dpId, String attachMac,
188                                             int addOrRemove);
189
190     /**
191      * Programs the ace custom rule.
192      *
193      * @param dpId the dpId
194      * @param attachMac the attached mac
195      * @param addOrRemove whether to delete or add flow
196      * @param ace rule to be program
197      */
198     protected abstract void programAceRule(BigInteger dpId, String attachMac, int addOrRemove, Ace ace);
199
200     /**
201      * Writes/remove the flow to/from the datastore.
202      * @param dpId the dpId
203      * @param tableId the tableId
204      * @param flowId the flowId
205      * @param priority the priority
206      * @param flowName the flow name
207      * @param idleTimeOut the idle timeout
208      * @param hardTimeOut the hard timeout
209      * @param cookie the cookie
210      * @param matches the list of matches to be writted
211      * @param instructions the list of instruction to be written.
212      * @param addOrRemove add or remove the entries.
213      */
214     protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
215                           int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase>  matches,
216                           List<InstructionInfo> instructions, int addOrRemove) {
217         if (addOrRemove == NwConstants.DEL_FLOW) {
218             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,flowId,
219                 priority, flowName , idleTimeOut, hardTimeOut, cookie, matches, null);
220             LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
221             mdsalManager.removeFlow(flowEntity);
222         } else {
223             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId,
224                 priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions);
225             LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
226             mdsalManager.installFlow(flowEntity);
227         }
228     }
229 }