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
9 package org.opendaylight.netvirt.aclservice.utils;
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.NxMatchFieldType;
29 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
30 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
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.inet.types.rev130715.IpAddress;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
63 import org.opendaylight.yangtools.yang.binding.DataObject;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
66 import org.opendaylight.yangtools.yang.common.RpcResult;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public class AclServiceUtils {
72 private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
74 private AclServiceUtils() { }
77 * Retrieves the Interface from the datastore.
78 * @param broker the data broker
79 * @param interfaceName the interface name
80 * @return the interface.
82 public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
83 .Interface> getInterface(DataBroker broker, String interfaceName) {
84 return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
88 * Builds the interface identifier.
89 * @param interfaceName the interface name.
90 * @return the interface identifier.
92 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
93 .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
94 return InstanceIdentifier.builder(Interfaces.class)
96 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
97 .Interface.class, new InterfaceKey(interfaceName)).build();
101 * Retrieves the object from the datastore.
102 * @param broker the data broker.
103 * @param datastoreType the data store type.
104 * @param path the wild card path.
105 * @return the required object.
107 public static <T extends DataObject> Optional<T> read(
108 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
110 Optional<T> result = Optional.absent();
111 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
113 result = tx.read(datastoreType, path).checkedGet();
114 } catch (ReadFailedException e) {
115 LOG.warn("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
123 * Retrieves the acl matching the key from the data store.
125 * @param broker the data broker
126 * @param aclKey the acl key
129 public static Acl getAcl(DataBroker broker, String aclKey) {
130 Optional<Acl> optAcl = read(broker,
131 LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey));
132 if (optAcl.isPresent()) {
138 /** Creates the Acl instance identifier.
140 * @param aclKey the acl key
141 * @return the instance identifier
143 public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
144 return InstanceIdentifier
145 .builder(AccessLists.class)
147 new AclKey(aclKey,Ipv4Acl.class))
152 * Get the data path number for the interface.
153 * @param interfaceManagerRpcService interfaceManagerRpcService instance.
154 * @param ifName the interface name.
157 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
158 BigInteger nodeId = BigInteger.ZERO;
160 GetDpidFromInterfaceInput dpIdInput =
161 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
162 Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
163 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
164 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
165 if (dpIdResult.isSuccessful()) {
166 nodeId = dpIdResult.getResult().getDpid();
168 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
170 } catch (NullPointerException | InterruptedException | ExecutionException e) {
171 LOG.error("Exception when getting dpn for interface {}", ifName, e);
177 * Retrieves the interface state.
178 * @param dataBroker the data broker.
179 * @param interfaceName the interface name.
180 * @return the interface state.
182 public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
183 .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
184 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
185 .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
186 Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
187 .interfaces.state.Interface> ifStateOptional = MDSALUtil.read(LogicalDatastoreType
188 .OPERATIONAL, ifStateId, dataBroker);
189 if (!ifStateOptional.isPresent()) {
193 return ifStateOptional.get();
197 * Build the interface state.
198 * @param interfaceName the interface name.
199 * @return the interface state.
201 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
202 .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
203 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
204 .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
205 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
206 .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
207 .rev140508.interfaces.state.InterfaceKey(interfaceName));
208 return idBuilder.build();
212 * Checks whether port security is enabled for the port.
213 * @param port the port.
214 * @return the port security is enabled/not.
216 public static boolean isPortSecurityEnabled(Interface port) {
218 LOG.error("Port is Null");
221 InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
222 if (aclInPort == null) {
223 LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
226 return aclInPort.isPortSecurityEnabled();
230 * Checks whether port security is enabled for the port.
231 * @param port the port.
232 * @return the list of security groups.
234 public static List<Uuid> getInterfaceAcls(Interface port) {
236 LOG.error("Port is Null");
239 InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
240 if (aclInPort == null) {
241 LOG.error("getSecurityGroupInPortList: no security group associated}",
245 return aclInPort.getSecurityGroups();
249 * Retrieves the security rule attribute augmentation from the access list.
250 * @param ace the access list entry
251 * @return the security rule attributes
253 public static SecurityRuleAttr getAccesssListAttributes(Ace ace) {
255 LOG.error("Ace is Null");
258 SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
259 if (aceAttributes == null) {
260 LOG.error("Ace is null");
263 return aceAttributes;
267 * Returns the DHCP match.
268 * @param srcPort the source port.
269 * @param dstPort the destination port.
270 * @return list of matches.
272 private static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, MatchInfo portMatch) {
273 List<MatchInfoBase> matches = new ArrayList<>(6);
274 matches.add(new MatchInfo(MatchFieldType.eth_type,
275 new long[] { NwConstants.ETHTYPE_IPV4 }));
276 matches.add(new MatchInfo(MatchFieldType.ip_proto,
277 new long[] { IPProtocols.UDP.intValue() }));
278 matches.add(new MatchInfo(MatchFieldType.udp_dst,
279 new long[] { srcPort }));
280 matches.add(new MatchInfo(MatchFieldType.udp_src,
281 new long[] { dstPort}));
282 matches.add(portMatch);
283 matches.add(new NxMatchInfo(NxMatchFieldType.ct_state,
284 new long[] { AclConstants.TRACKED_NEW_CT_STATE, AclConstants.TRACKED_NEW_CT_STATE_MASK}));
289 * Builds a list of matches for DHCP filtering on the source's MAC address.
291 * @param srcPort The source port.
292 * @param dstPort The destination port.
293 * @param attachMac The attached port's MAC address.
295 * @return The matches.
297 public static List<MatchInfoBase> buildDhcpSourceMatches(int srcPort, int dstPort, String attachMac) {
298 return buildDhcpMatches(srcPort, dstPort, new MatchInfo(MatchFieldType.eth_src, new String[] { attachMac }));
302 * Builds a list of matches for DHCP filtering on the destination's MAC address.
304 * @param srcPort The source port.
305 * @param dstPort The destination port.
306 * @param attachMac The attached port's MAC address.
308 * @return The matches.
310 public static List<MatchInfoBase> buildDhcpDestinationMatches(int srcPort, int dstPort, String attachMac) {
311 return buildDhcpMatches(srcPort, dstPort, new MatchInfo(MatchFieldType.eth_dst, new String[] { attachMac }));
315 * Builds the service id.
317 * @param interfaceName the interface name
318 * @param serviceIndex the service index
319 * @param serviceMode the service mode
320 * @return the instance identifier
322 public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
323 Class<? extends ServiceModeBase> serviceMode) {
324 return InstanceIdentifier.builder(ServiceBindings.class)
325 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
326 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
330 * Gets the bound services.
332 * @param serviceName the service name
333 * @param servicePriority the service priority
334 * @param flowPriority the flow priority
335 * @param cookie the cookie
336 * @param instructions the instructions
337 * @return the bound services
339 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
340 BigInteger cookie, List<Instruction> instructions) {
341 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
342 .setInstruction(instructions);
343 return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
344 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
345 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
348 public static List<Uuid> getUpdatedAclList(Interface updatedPort, Interface currentPort) {
349 if (updatedPort == null) {
352 List<Uuid> updatedAclList = new ArrayList<>(AclServiceUtils.getInterfaceAcls(updatedPort));
353 if (currentPort == null) {
354 return updatedAclList;
356 List<Uuid> currentAclList = new ArrayList<>(AclServiceUtils.getInterfaceAcls(currentPort));
357 for (Iterator<Uuid> iterator = updatedAclList.iterator(); iterator.hasNext();) {
358 Uuid updatedAclUuid = iterator.next();
359 for (Uuid currentAclUuid :currentAclList) {
360 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
365 return updatedAclList;
368 public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(Interface updatedPort,
369 Interface currentPort) {
370 if (updatedPort == null) {
373 List<AllowedAddressPairs> updatedAllowedAddressPairs =
374 new ArrayList<>(AclServiceUtils.getPortAllowedAddresses(updatedPort));
375 if (currentPort == null) {
376 return updatedAllowedAddressPairs;
378 List<AllowedAddressPairs> currentAllowedAddressPairs =
379 new ArrayList<>(AclServiceUtils.getPortAllowedAddresses(currentPort));
380 for (Iterator<AllowedAddressPairs> iterator = updatedAllowedAddressPairs.iterator(); iterator.hasNext();) {
381 AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
382 for (AllowedAddressPairs currentAllowedAddressPair : currentAllowedAddressPairs) {
383 if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
389 return updatedAllowedAddressPairs;
392 public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
394 LOG.error("Port is Null");
397 InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
398 if (aclInPort == null) {
399 LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
402 return aclInPort.getAllowedAddressPairs();
405 public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
406 .interfaces.rev140508.interfaces.state.Interface interfaceState) {
407 BigInteger dpId = null;
408 String interfaceName = interfaceState.getName();
409 List<String> ofportIds = interfaceState.getLowerLayerIf();
410 if (ofportIds != null && !ofportIds.isEmpty()) {
411 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
412 dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
417 public static List<MatchInfoBase> getAllowedIpMatches(IpPrefixOrAddress allowedIp, MatchFieldType ipv4MatchType) {
418 List<MatchInfoBase> flowMatches = new ArrayList<>();
419 flowMatches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 }));
420 IpPrefix ipPrefix = allowedIp.getIpPrefix();
421 if (ipPrefix != null) {
422 if (ipPrefix.getIpv4Prefix().getValue() != null) {
423 String[] ipaddressValues = ipPrefix.getIpv4Prefix().getValue().split("/");
424 flowMatches.add(new MatchInfo(ipv4MatchType, new String[] {ipaddressValues[0], ipaddressValues[1]}));
429 IpAddress ipAddress = allowedIp.getIpAddress();
430 if (ipAddress.getIpv4Address() != null) {
431 flowMatches.add(new MatchInfo(ipv4MatchType,
432 new String[] {ipAddress.getIpv4Address().getValue(), "32"}));
440 public static List<MatchInfo> getLPortTagMatches(int lportTag) {
441 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
443 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
444 MetaDataUtil.getLportTagMetaData(lportTag),
445 MetaDataUtil.METADATA_MASK_LPORT_TAG }));
446 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(lportTag)}));