2 * Copyright (c) 2017 Cisco Systems. 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.groupbasedpolicy.renderer.vpp.lisp.util;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
16 import java.util.List;
20 import javax.annotation.Nonnull;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
32 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
33 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.InterfaceUtil;
34 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
35 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
36 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLength;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev171013.HmacKeyType;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev171013.dp.subtable.grouping.local.mappings.local.mapping.Eid;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev171013.hmac.key.grouping.HmacKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
76 public class ConfigManagerHelper {
77 private static final Logger LOG = LoggerFactory.getLogger(ConfigManagerHelper.class);
79 private MountedDataBrokerProvider mountedDataBrokerProvider;
81 public ConfigManagerHelper(MountedDataBrokerProvider mountedDataBrokerProvider) {
82 this.mountedDataBrokerProvider = mountedDataBrokerProvider;
86 public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
87 Preconditions.checkNotNull(addrEpWithLoc.getAbsoluteLocation(), "Absolute location for " +
88 "AddressEndpointWithLocation missing: " + addrEpWithLoc.toString() );
89 LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
90 if (!(locationType instanceof ExternalLocationCase)) {
91 throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
93 ExternalLocationCase result = (ExternalLocationCase) locationType;
94 if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
95 throw new IllegalArgumentException(
96 "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
101 //This is almost identical to VBD's equivalent method
102 public ListenableFuture<String> getLispDataRlocInterfaceName(@Nonnull String hostName) {
103 Preconditions.checkNotNull(hostName, "Hostname is null!");
105 PhysicalInterfaces physicalInterfaces = HostRelatedInfoContainer.getInstance()
106 .getPhysicalInterfaceState(hostName);
108 String publicInterfaceName = physicalInterfaces == null ? "" : physicalInterfaces
109 .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
111 final Optional<InterfacesState> opInterfaceState =
112 GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.OPERATIONAL,
113 InstanceIdentifier.create(InterfacesState.class), GbpNetconfTransaction.RETRY_COUNT);
115 if (!opInterfaceState.isPresent()) {
116 LOG.debug("There appear to be no interfaces on node {}.", hostName);
117 return Futures.immediateFailedFuture(new LispNotFoundException("No interfaces found"));
120 String interfaceName = null;
121 for(Interface intf: opInterfaceState.get().getInterface()) {
122 if(!ipAddressPresent(intf)) {
125 interfaceName = intf.getName();
128 final Optional<Interfaces> opInterfaces =
129 GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.CONFIGURATION,
130 InstanceIdentifier.create(Interfaces.class), GbpNetconfTransaction.RETRY_COUNT);
133 if (opInterfaces.isPresent()) {
135 List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
136 interfaces.Interface> hostInterfaceFromOpDS = opInterfaces.get().getInterface();
138 for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
139 interfaces.Interface intf : hostInterfaceFromOpDS) {
140 if (Constants.TENANT_INTERFACE.equals(intf.getDescription())
141 && ipAddressPresent(intf)
142 && intf.getType().equals(EthernetCsmacd.class)) {
143 return Futures.immediateFuture(intf.getName());
147 for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
148 interfaces.Interface intf : hostInterfaceFromOpDS) {
149 if (ipAddressPresent(intf)
150 && intf.getType().equals(EthernetCsmacd.class)
151 && !intf.getName().equalsIgnoreCase(publicInterfaceName)) {
152 return Futures.immediateFuture(intf.getName());
157 if (interfaceName == null) {
158 LOG.warn("No interface with IP found for host {}", hostName);
159 return Futures.immediateFailedFuture(new LispNotFoundException("No interface with Ip address found!"));
161 return Futures.immediateFuture(interfaceName);
164 private boolean ipAddressPresent(Interface intf) {
165 Interface2 augIntf = intf.getAugmentation(Interface2.class);
167 if (augIntf == null) {
171 Ipv4 ipv4 = augIntf.getIpv4();
177 final List<Address> addresses = ipv4.getAddress();
179 if (addresses == null || addresses.isEmpty()) {
183 final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
187 private String ipCidr(Interface intf) {
188 Interface2 augIntf = intf.getAugmentation(Interface2.class);
190 if (augIntf == null) {
194 Ipv4 ipv4 = augIntf.getIpv4();
200 final List<Address> addresses = ipv4.getAddress();
202 if (addresses == null || addresses.isEmpty()) {
206 Address firstAddress = addresses.get(0);
207 String ipString = firstAddress.getIp().getValue();
209 if (firstAddress.getSubnet().getImplementedInterface().equals(PrefixLength.class)) {
210 length = "" + ((PrefixLength)firstAddress.getSubnet()).getPrefixLength();
213 if (length.isEmpty()) {
217 return ipString + "/" + length;
220 private boolean ipAddressPresent(final org.opendaylight.yang.gen.v1.urn.ietf.
221 params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intf) {
222 final Interface1 augIntf = intf.getAugmentation(Interface1.class);
224 if (augIntf == null) {
225 LOG.debug("Cannot get Interface1 augmentation for intf {}", intf);
229 final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4 ipv4 =
235 final List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address> addresses =
237 if (addresses == null || addresses.isEmpty()) {
241 final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
245 public String getLispCpRlocInterfaceName(@Nonnull String hostName) {
246 List<Interface> operationalInterfaceList =
247 InterfaceUtil.getOperationalInterfaces(LispUtil.HOSTNAME_TO_IID.apply(hostName));
249 if (operationalInterfaceList == null) {
253 String outgoingInterface = "";
255 for (Interface intf : operationalInterfaceList) {
256 String ipCidr = ipCidr(intf);
258 if (ipCidr == null) {
262 if (IpAddressUtil.ipInRange(ConfigUtil.getInstance().getOdlIp().getIpv4Address(),
263 IpAddressUtil.startIpOfSubnet(ipCidr), IpAddressUtil.endIpOfSubnet(ipCidr))) {
264 int tmpLen = IpAddressUtil.maskLen(ipCidr);
265 if (tmpLen > maxLen) {
267 outgoingInterface = intf.getName();
271 return outgoingInterface;
275 public String constructLocatorSetName(int locatorSetCount) {
276 return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + (locatorSetCount + 1);
279 public String constructLocatorSetNameForItrRloc() {
280 return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + "_itr_rloc";
283 public String constructEidMappingName(AddressEndpointWithLocation addressEp, String interfaceName) {
284 String ipAddress = getInterfaceIp(addressEp).getValue();
285 return LispStateManager.DEFAULT_MAPPING_RECORD_NAME_PREFIX + interfaceName + "_" + ipAddress;
288 public String getSubnet(AddressEndpointWithLocation addressEp) {
289 String subnetUuid = null;
290 Containment containment = addressEp.getNetworkContainment().getContainment();
291 if (containment instanceof NetworkDomainContainment) {
292 NetworkDomainContainment networkDomainContainment = (NetworkDomainContainment) containment;
293 subnetUuid = networkDomainContainment.getNetworkDomainId().getValue();
298 public Eid getEid(AddressEndpointWithLocation addressEp, long vni) {
299 String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
300 return LispUtil.toEid(LispUtil.toIpv4(ipPrefix), vni, Ipv4Afi.class);
303 private static String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
304 String ipPrefix = null;
305 if (addressEp.getAddressType().equals(IpPrefixType.class)) {
306 ipPrefix = addressEp.getAddress();
307 } else if (addressEp.getAddressType().equals(MacAddressType.class)) {
308 ParentEndpointChoice parentEndpointChoice = addressEp.getParentEndpointChoice();
309 if (parentEndpointChoice instanceof ParentEndpointCase) {
310 java.util.Optional<ParentEndpoint> endpointOptional =
311 ((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().stream()
312 .filter(choice -> choice.getAddressType().equals(IpPrefixType.class))
313 .filter(choice -> choice.getContextType().equals(L3Context.class)).findFirst();
314 if (endpointOptional.isPresent()) {
315 ipPrefix = endpointOptional.get().getAddress();
319 return Preconditions.checkNotNull(ipPrefix, "No IP address found for Address Endpoint: {}", addressEp);
322 public static Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
323 String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
324 return LispUtil.toIpv4(ipPrefix).getIpv4();
327 public Ipv4Prefix getInterfaceIpAsPrefix(AddressEndpointWithLocation addressEp) {
328 if (getInterfaceIp(addressEp).getValue().contains("/")) {
329 return new Ipv4Prefix(getInterfaceIp(addressEp).getValue());
332 return new Ipv4Prefix(getInterfaceIp(addressEp).getValue() + "/32");
336 public String getFirstLocatorSetName(LispState lispState) {
337 Set<Map.Entry<String, String >> locatorSet = lispState.getLocatorSetEntry();
338 Preconditions.checkNotNull(locatorSet, "No locator set found!");
339 if (!locatorSet.iterator().hasNext()) {
343 return locatorSet.iterator().next().getValue();
346 public Optional<String> getInterfaceName(AddressEndpointWithLocation addedEp) {
347 ExternalLocationCase epLoc = resolveAndValidateLocation(addedEp);
348 String interfacePath = epLoc.getExternalNodeConnector();
350 return VppPathMapper.interfacePathToInterfaceName(interfacePath);
353 public Optional<String> getInterfaceName(ExternalLocation externalLocation) {
354 String interfacePath = externalLocation.getExternalNodeConnector();
355 return VppPathMapper.interfacePathToInterfaceName(interfacePath);
359 public HmacKey getDefaultHmacKey() {
360 return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
363 public String getPhysicalAddress(AddressEndpointWithLocation addressEp) {
364 String physicalAddress = null;
366 if (addressEp.getAddressType().equals(MacAddressType.class)) {
367 physicalAddress = addressEp.getAddress();
369 List<ChildEndpoint> childEndpoints = addressEp.getChildEndpoint();
370 for (ChildEndpoint childEndpoint : childEndpoints) {
371 if (childEndpoint.getAddressType().equals(MacAddressType.class)) {
372 physicalAddress = childEndpoint.getAddress();
377 return Preconditions.checkNotNull(physicalAddress, "Physical address not found " +
378 "in address endpoint: " + addressEp);
381 public boolean hasRelativeLocations(AddressEndpointWithLocation addedEp) {
382 return addedEp.getRelativeLocations() != null && addedEp.getRelativeLocations().getExternalLocation() != null;
385 public static boolean isMetadataPort(AddressEndpointWithLocation addressEp) {
386 return IpAddressUtil.isMetadataIp(getInterfaceIp(addressEp));
389 public String getGatewayInterfaceName(String gwNamePrefix, String subnetUuid) {
390 return gwNamePrefix + subnetUuid;
393 public Routing getRouting(long vrf) {
394 return new RoutingBuilder().setIpv4VrfId(vrf).build();