Merge "Commented out frequently replayed BGPMIP errorlogs"
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / utils / AclServiceUtils.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
9 package org.opendaylight.netvirt.aclservice.utils;
10
11 import com.google.common.base.Optional;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.genius.mdsalutil.MatchFieldType;
24 import org.opendaylight.genius.mdsalutil.MatchInfo;
25 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
26 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
29 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
62 import org.opendaylight.yangtools.yang.binding.DataObject;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
65 import org.opendaylight.yangtools.yang.common.RpcResult;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69 public final class AclServiceUtils {
70
71     private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
72
73     private AclServiceUtils() { }
74
75     /**
76      * Retrieves the Interface from the datastore.
77      * @param broker the data broker
78      * @param interfaceName the interface name
79      * @return the interface.
80      */
81     public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
82         .Interface> getInterface(DataBroker broker, String interfaceName) {
83         return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
84     }
85
86     /**
87      * Builds the interface identifier.
88      * @param interfaceName the interface name.
89      * @return the interface identifier.
90      */
91     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
92         .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
93         return InstanceIdentifier.builder(Interfaces.class)
94                 .child(
95                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
96                     .Interface.class, new InterfaceKey(interfaceName)).build();
97     }
98
99     /**
100      * Retrieves the object from the datastore.
101      * @param broker the data broker.
102      * @param datastoreType the data store type.
103      * @param path the wild card path.
104      * @return the required object.
105      */
106     public static <T extends DataObject> Optional<T> read(
107             DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
108
109         Optional<T> result = Optional.absent();
110         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
111         try {
112             result = tx.read(datastoreType, path).checkedGet();
113         } catch (ReadFailedException e) {
114             LOG.warn("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
115         } finally {
116             tx.close();
117         }
118         return result;
119     }
120
121     /**
122      * Retrieves the acl matching the key from the data store.
123      *
124      * @param broker the data broker
125      * @param aclKey the acl key
126      * @return the acl
127      */
128     public static Acl getAcl(DataBroker broker, String aclKey) {
129         Optional<Acl> optAcl = read(broker,
130             LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey));
131         if (optAcl.isPresent()) {
132             return optAcl.get();
133         }
134         return null;
135     }
136
137     /** Creates the Acl instance identifier.
138      *
139      * @param aclKey the acl key
140      * @return the instance identifier
141      */
142     public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
143         return InstanceIdentifier
144                 .builder(AccessLists.class)
145                 .child(Acl.class,
146                         new AclKey(aclKey,Ipv4Acl.class))
147                 .build();
148     }
149
150     /**
151      * Get the data path number for the interface.
152      * @param interfaceManagerRpcService interfaceManagerRpcService instance.
153      * @param ifName the interface name.
154      * @return the dpn.
155      */
156     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
157         BigInteger nodeId = BigInteger.ZERO;
158         try {
159             GetDpidFromInterfaceInput dpIdInput =
160                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
161             Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
162                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
163             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
164             if (dpIdResult.isSuccessful()) {
165                 nodeId = dpIdResult.getResult().getDpid();
166             } else {
167                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
168             }
169         } catch (NullPointerException | InterruptedException | ExecutionException e) {
170             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
171         }
172         return nodeId;
173     }
174
175     /**
176      * Retrieves the interface state.
177      * @param dataBroker the data broker.
178      * @param interfaceName the interface name.
179      * @return the interface state.
180      */
181     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
182         .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
183         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
184             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
185         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
186             .interfaces.state.Interface> ifStateOptional = MDSALUtil.read(LogicalDatastoreType
187                 .OPERATIONAL, ifStateId, dataBroker);
188         if (!ifStateOptional.isPresent()) {
189             return null;
190         }
191
192         return ifStateOptional.get();
193     }
194
195     /**
196      * Build the interface state.
197      * @param interfaceName the interface name.
198      * @return the interface state.
199      */
200     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
201         .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
202         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
203             .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
204             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
205             .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
206             .rev140508.interfaces.state.InterfaceKey(interfaceName));
207         return idBuilder.build();
208     }
209
210     /**
211      * Checks whether port security is enabled for the port.
212      * @param port the port.
213      * @return the port security is enabled/not.
214      */
215     public static boolean isPortSecurityEnabled(AclInterface port) {
216         return port.isPortSecurityEnabled();
217     }
218
219     /**
220      * Checks whether port security is enabled for the port.
221      * @param port the port.
222      * @return the list of security groups.
223      */
224     public static List<Uuid> getInterfaceAcls(Interface port) {
225         if (port == null) {
226             LOG.error("Port is Null");
227             return null;
228         }
229         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
230         if (aclInPort == null) {
231             LOG.error("getSecurityGroupInPortList: no security group associated}",
232                 port.getName());
233             return null;
234         }
235         return aclInPort.getSecurityGroups();
236     }
237
238     /**
239      * Retrieves the security rule attribute augmentation from the access list.
240      * @param ace the access list entry
241      * @return the security rule attributes
242      */
243     public static SecurityRuleAttr  getAccesssListAttributes(Ace ace) {
244         if (ace == null) {
245             LOG.error("Ace is Null");
246             return null;
247         }
248         SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
249         if (aceAttributes == null) {
250             LOG.error("Ace is null");
251             return null;
252         }
253         return aceAttributes;
254     }
255
256     /**
257      * Returns the DHCP match.
258      *
259      * @param srcPort the source port.
260      * @param dstPort the destination port.
261      * @param lportTag the lport tag
262      * @return list of matches.
263      */
264     public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag) {
265         List<MatchInfoBase> matches = new ArrayList<>(6);
266         matches.add(new MatchInfo(MatchFieldType.eth_type,
267                 new long[] { NwConstants.ETHTYPE_IPV4 }));
268         matches.add(new MatchInfo(MatchFieldType.ip_proto,
269                 new long[] { IPProtocols.UDP.intValue() }));
270         matches.add(new MatchInfo(MatchFieldType.udp_dst,
271                 new long[] { dstPort }));
272         matches.add(new MatchInfo(MatchFieldType.udp_src,
273                 new long[] { srcPort}));
274         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
275         return matches;
276     }
277
278     /**
279      * Builds the service id.
280      *
281      * @param interfaceName the interface name
282      * @param serviceIndex the service index
283      * @param serviceMode the service mode
284      * @return the instance identifier
285      */
286     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
287             Class<? extends ServiceModeBase> serviceMode) {
288         return InstanceIdentifier.builder(ServiceBindings.class)
289                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
290                 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
291     }
292
293     /**
294      * Gets the bound services.
295      *
296      * @param serviceName the service name
297      * @param servicePriority the service priority
298      * @param flowPriority the flow priority
299      * @param cookie the cookie
300      * @param instructions the instructions
301      * @return the bound services
302      */
303     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
304             BigInteger cookie, List<Instruction> instructions) {
305         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
306                 .setInstruction(instructions);
307         return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
308                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
309                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
310     }
311
312     public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
313         if (updatedAclList == null) {
314             return null;
315         }
316         List<Uuid> newAclList = new ArrayList<>(updatedAclList);
317         if (currentAclList == null) {
318             return newAclList;
319         }
320         List<Uuid> origAclList = new ArrayList<>(currentAclList);
321         for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
322             Uuid updatedAclUuid = iterator.next();
323             for (Uuid currentAclUuid :origAclList) {
324                 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
325                     iterator.remove();
326                 }
327             }
328         }
329         return newAclList;
330     }
331
332     public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
333             List<AllowedAddressPairs> updatedAllowedAddressPairs,
334             List<AllowedAddressPairs> currentAllowedAddressPairs) {
335         if (updatedAllowedAddressPairs == null) {
336             return null;
337         }
338         List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
339         if (currentAllowedAddressPairs == null) {
340             return newAllowedAddressPairs;
341         }
342         List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
343         for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
344             AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
345             for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
346                 if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
347                     iterator.remove();
348                     break;
349                 }
350             }
351         }
352         return newAllowedAddressPairs;
353     }
354
355     public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
356         if (port == null) {
357             LOG.error("Port is Null");
358             return null;
359         }
360         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
361         if (aclInPort == null) {
362             LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
363             return null;
364         }
365         return aclInPort.getAllowedAddressPairs();
366     }
367
368     public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
369             .interfaces.rev140508.interfaces.state.Interface interfaceState) {
370         BigInteger dpId = null;
371         String interfaceName = interfaceState.getName();
372         List<String> ofportIds = interfaceState.getLowerLayerIf();
373         if (ofportIds != null && !ofportIds.isEmpty()) {
374             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
375             dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
376         }
377         return dpId;
378     }
379
380     /**
381      * Builds the ip matches.
382      *
383      * @param ipPrefixOrAddress the ip prefix or address
384      * @param ipv4MatchType the ipv4 match type
385      * @return the list
386      */
387     public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
388             MatchFieldType ipv4MatchType) {
389         List<MatchInfoBase> flowMatches = new ArrayList<>();
390         flowMatches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV4}));
391         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
392         if (ipPrefix != null) {
393             if (ipPrefix.getIpv4Prefix().getValue() != null) {
394                 String[] ipaddressValues = ipPrefix.getIpv4Prefix().getValue().split("/");
395                 flowMatches.add(new MatchInfo(ipv4MatchType, new String[] {ipaddressValues[0], ipaddressValues[1]}));
396             } else {
397                 // Handle IPv6
398             }
399         } else {
400             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
401             if (ipAddress.getIpv4Address() != null) {
402                 flowMatches
403                         .add(new MatchInfo(ipv4MatchType, new String[] {ipAddress.getIpv4Address().getValue(), "32"}));
404             } else {
405                 // Handle IPv6
406             }
407         }
408         return flowMatches;
409     }
410
411     /**
412      * Gets the lport tag match.
413      *
414      * @param lportTag the lport tag
415      * @return the lport tag match
416      */
417     public static MatchInfo buildLPortTagMatch(int lportTag) {
418         return new MatchInfo(MatchFieldType.metadata,
419                 new BigInteger[] {MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG});
420     }
421 }