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 java.util.List;
15 import javax.annotation.Nonnull;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.InterfaceUtil;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLength;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.hmac.key.grouping.HmacKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
71 import com.google.common.base.Optional;
72 import com.google.common.base.Preconditions;
73 import com.google.common.util.concurrent.Futures;
74 import com.google.common.util.concurrent.ListenableFuture;
78 * Created by Shakib Ahmed on 3/31/17.
80 public class ConfigManagerHelper {
81 private static final Logger LOG = LoggerFactory.getLogger(ConfigManagerHelper.class);
83 private MountedDataBrokerProvider mountedDataBrokerProvider;
85 public ConfigManagerHelper(MountedDataBrokerProvider mountedDataBrokerProvider) {
86 this.mountedDataBrokerProvider = mountedDataBrokerProvider;
89 public EndpointHost getEndpointHostInformation(AddressEndpointWithLocation addressEpWithLoc) {
90 DataBroker endpointHostDataBroker = getPotentialExternalDataBroker(addressEpWithLoc).get();
91 String hostName = getHostName(addressEpWithLoc).get();
92 return new EndpointHost(endpointHostDataBroker, hostName);
95 public Optional<DataBroker> getPotentialExternalDataBroker(AddressEndpointWithLocation addressEpWithLoc) {
96 ExternalLocationCase externalLocationCase = resolveAndValidateLocation(addressEpWithLoc);
97 InstanceIdentifier<Node> vppNodeIid =
98 (InstanceIdentifier<Node>) externalLocationCase.getExternalNodeMountPoint();
99 String interfacePath = externalLocationCase.getExternalNodeConnector();
102 potentialVppDataProvider = mountedDataBrokerProvider.resolveDataBrokerForMountPoint(vppNodeIid);
104 Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
105 "Cannot resolve data broker for interface path: {}", interfacePath);
107 return potentialVppDataProvider;
110 public Optional<DataBroker> getPotentialExternalDataBroker(ExternalLocation externalLocation) {
111 InstanceIdentifier<Node> vppNodeIid = (InstanceIdentifier<Node>) externalLocation.getExternalNodeMountPoint();
113 Optional<DataBroker> potentialVppDataProvider;
114 potentialVppDataProvider = mountedDataBrokerProvider.resolveDataBrokerForMountPoint(vppNodeIid);
116 Preconditions.checkState(potentialVppDataProvider.isPresent(), "Data Broker missing");
118 return potentialVppDataProvider;
121 public Optional<DataBroker> getPotentialExternalDataBroker(VppEndpoint vppEp) {
122 InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(vppEp.getVppNodeId());
123 Optional<DataBroker> potentialVppDataProvider =
124 mountedDataBrokerProvider.resolveDataBrokerForMountPoint(vppNodeIid);
126 Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
127 "Cannot resolve data broker for Vpp Endpoint: {}", vppEp);
128 return potentialVppDataProvider;
131 public Optional<DataBroker> getPotentialExternalDataBroker(String hostId) {
132 InstanceIdentifier<Node> nodeIid = VppIidFactory.getNetconfNodeIid(new NodeId(hostId));
133 Optional<DataBroker> potentialVppDataProvider =
134 mountedDataBrokerProvider.resolveDataBrokerForMountPoint(nodeIid);
135 Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
136 "Data Broker not found for {}", hostId);
137 return potentialVppDataProvider;
140 public Optional<String> getHostName(AddressEndpointWithLocation addrEp) {
141 ExternalLocationCase locationCase = resolveAndValidateLocation(addrEp);
142 NodeKey nodeKey = locationCase.getExternalNodeMountPoint().firstKeyOf(Node.class);
143 String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
144 "Host Id extraction failed from address endpoint: {}", addrEp);
145 return Optional.fromNullable(hostId);
148 public Optional<String> getHostName(ExternalLocation externalLocation) {
149 NodeKey nodeKey = externalLocation.getExternalNodeMountPoint().firstKeyOf(Node.class);
150 String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
151 "Host Id extraction failed from address endpoint: {}", externalLocation);
153 return Optional.fromNullable(hostId);
156 public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
157 Preconditions.checkNotNull(addrEpWithLoc.getAbsoluteLocation(), "Absolute location for " +
158 "AddressEndpointWithLocation missing: " + addrEpWithLoc.toString() );
159 LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
160 if (!(locationType instanceof ExternalLocationCase)) {
161 throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
163 ExternalLocationCase result = (ExternalLocationCase) locationType;
164 if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
165 throw new IllegalArgumentException(
166 "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
171 //This is almost identical to VBD's equivalent method
172 public ListenableFuture<String> getLispDataRlocInterfaceName(@Nonnull String hostName) {
173 Preconditions.checkNotNull(hostName, "Hostname is null!");
175 PhysicalInterfaces physicalInterfaces = HostRelatedInfoContainer.getInstance()
176 .getPhysicalInterfaceState(hostName);
178 String publicInterfaceName = physicalInterfaces == null ? "" : physicalInterfaces
179 .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
181 final Optional<InterfacesState> opInterfaceState =
182 GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.OPERATIONAL,
183 InstanceIdentifier.create(InterfacesState.class), GbpNetconfTransaction.RETRY_COUNT);
185 if (!opInterfaceState.isPresent()) {
186 LOG.debug("There appear to be no interfaces on node {}.", hostName);
187 return Futures.immediateFailedFuture(new LispNotFoundException("No interfaces found"));
190 String interfaceName = null;
191 for(Interface intf: opInterfaceState.get().getInterface()) {
192 if(!ipAddressPresent(intf)) {
195 interfaceName = intf.getName();
198 final Optional<Interfaces> opInterfaces =
199 GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.CONFIGURATION,
200 InstanceIdentifier.create(Interfaces.class), GbpNetconfTransaction.RETRY_COUNT);
203 if (opInterfaces.isPresent()) {
205 List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
206 interfaces.Interface> hostInterfaceFromOpDS = opInterfaces.get().getInterface();
208 for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
209 interfaces.Interface intf : hostInterfaceFromOpDS) {
210 if (Constants.TENANT_INTERFACE.equals(intf.getDescription())
211 && ipAddressPresent(intf)
212 && intf.getType().equals(EthernetCsmacd.class)) {
213 return Futures.immediateFuture(intf.getName());
217 for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
218 interfaces.Interface intf : hostInterfaceFromOpDS) {
219 if (ipAddressPresent(intf)
220 && intf.getType().equals(EthernetCsmacd.class)
221 && !intf.getName().equalsIgnoreCase(publicInterfaceName)) {
222 return Futures.immediateFuture(intf.getName());
227 if (interfaceName == null) {
228 LOG.warn("No interface with IP found for host {}", hostName);
229 return Futures.immediateFailedFuture(new LispNotFoundException("No interface with Ip address found!"));
231 return Futures.immediateFuture(interfaceName);
234 private boolean ipAddressPresent(Interface intf) {
235 Interface2 augIntf = intf.getAugmentation(Interface2.class);
237 if (augIntf == null) {
241 Ipv4 ipv4 = augIntf.getIpv4();
247 final List<Address> addresses = ipv4.getAddress();
249 if (addresses == null || addresses.isEmpty()) {
253 final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
257 private String ipCidr(Interface intf) {
258 Interface2 augIntf = intf.getAugmentation(Interface2.class);
260 if (augIntf == null) {
264 Ipv4 ipv4 = augIntf.getIpv4();
270 final List<Address> addresses = ipv4.getAddress();
272 if (addresses == null || addresses.isEmpty()) {
276 Address firstAddress = addresses.get(0);
277 String ipString = firstAddress.getIp().getValue();
279 if (firstAddress.getSubnet().getImplementedInterface().equals(PrefixLength.class)) {
280 length = "" + ((PrefixLength)firstAddress.getSubnet()).getPrefixLength();
283 if (length.isEmpty()) {
287 return ipString + "/" + length;
290 private boolean ipAddressPresent(final org.opendaylight.yang.gen.v1.urn.ietf.
291 params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intf) {
292 final Interface1 augIntf = intf.getAugmentation(Interface1.class);
294 if (augIntf == null) {
295 LOG.debug("Cannot get Interface1 augmentation for intf {}", intf);
299 final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4 ipv4 =
305 final List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address> addresses =
307 if (addresses == null || addresses.isEmpty()) {
311 final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
315 public String getLispCpRlocInterfaceName(@Nonnull EndpointHost endpointHost) {
316 List<Interface> operationalInterfaceList =
317 InterfaceUtil.getOperationalInterfaces(LispUtil.HOSTNAME_TO_IID.apply(endpointHost.getHostName()));
319 if (operationalInterfaceList == null) {
323 String outgoingInterface = "";
325 for (Interface intf : operationalInterfaceList) {
326 String ipCidr = ipCidr(intf);
328 if (ipCidr == null) {
332 if (IpAddressUtil.ipInRange(ConfigUtil.getInstance().getOdlIp().getIpv4Address(),
333 IpAddressUtil.startIpOfSubnet(ipCidr), IpAddressUtil.endIpOfSubnet(ipCidr))) {
334 int tmpLen = IpAddressUtil.maskLen(ipCidr);
335 if (tmpLen > maxLen) {
337 outgoingInterface = intf.getName();
341 return outgoingInterface;
345 public String constructLocatorSetName(int locatorSetCount) {
346 return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + (locatorSetCount + 1);
349 public String constructLocatorSetNameForItrRloc() {
350 return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + "_itr_rloc";
353 public String constructEidMappingName(AddressEndpointWithLocation addressEp) {
354 String interfaceName = getInterfaceName(addressEp).get();
355 String ipAddress = getInterfaceIp(addressEp).getValue();
356 return LispStateManager.DEFAULT_MAPPINGRECORD_NAME_PREFIX + interfaceName + "_" + ipAddress;
359 public String getSubnet(AddressEndpointWithLocation addressEp) {
360 String subnetUuid = null;
361 Containment containment = addressEp.getNetworkContainment().getContainment();
362 if (containment instanceof NetworkDomainContainment) {
363 NetworkDomainContainment networkDomainContainment = (NetworkDomainContainment) containment;
364 subnetUuid = networkDomainContainment.getNetworkDomainId().getValue();
369 public Eid getEid(AddressEndpointWithLocation addressEp, long vni) {
370 String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
371 return LispUtil.toEid(LispUtil.toIpv4(ipPrefix), vni, Ipv4Afi.class);
374 public String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
375 String ipPrefix = null;
376 if (addressEp.getAddressType().equals(IpPrefixType.class)) {
377 ipPrefix = addressEp.getAddress();
378 } else if (addressEp.getAddressType().equals(MacAddressType.class)) {
379 ParentEndpointChoice parentEndpointChoice = addressEp.getParentEndpointChoice();
380 if (parentEndpointChoice instanceof ParentEndpointCase) {
381 java.util.Optional<ParentEndpoint> endpointOptional =
382 ((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().stream()
383 .filter(choice -> choice.getAddressType().equals(IpPrefixType.class))
384 .filter(choice -> choice.getContextType().equals(L3Context.class)).findFirst();
385 if (endpointOptional.isPresent()) {
386 ipPrefix = endpointOptional.get().getAddress();
390 return Preconditions.checkNotNull(ipPrefix, "No IP address found for Address Endpoint: {}", addressEp);
393 public Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
394 String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
395 return LispUtil.toIpv4(ipPrefix).getIpv4();
398 public Ipv4Prefix getInterfaceIpAsPrefix(AddressEndpointWithLocation addressEp) {
399 if (getInterfaceIp(addressEp).getValue().contains("/")) {
400 return new Ipv4Prefix(getInterfaceIp(addressEp).getValue());
403 return new Ipv4Prefix(getInterfaceIp(addressEp).getValue() + "/32");
407 public String getFirstLocatorSetName(LispState lispState) {
408 Set<Map.Entry<String, String >> locatorSet = lispState.getLocatorSetEntry();
409 Preconditions.checkNotNull(locatorSet, "No locator set found!");
410 if (!locatorSet.iterator().hasNext()) {
414 return locatorSet.iterator().next().getValue();
417 public Optional<String> getInterfaceName(AddressEndpointWithLocation addedEp) {
418 ExternalLocationCase epLoc = resolveAndValidateLocation(addedEp);
419 String interfacePath = epLoc.getExternalNodeConnector();
421 return VppPathMapper.interfacePathToInterfaceName(interfacePath);
424 public Optional<String> getInterfaceName(ExternalLocation externalLocation) {
425 String interfacePath = externalLocation.getExternalNodeConnector();
426 return VppPathMapper.interfacePathToInterfaceName(interfacePath);
429 public HmacKey getDefaultHmacKey() {
430 return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
433 public String getPhysicalAddress(AddressEndpointWithLocation addressEp) {
434 String physicalAddress = null;
436 if (addressEp.getAddressType().equals(MacAddressType.class)) {
437 physicalAddress = addressEp.getAddress();
439 List<ChildEndpoint> childEndpoints = addressEp.getChildEndpoint();
440 for (ChildEndpoint childEndpoint : childEndpoints) {
441 if (childEndpoint.getAddressType().equals(MacAddressType.class)) {
442 physicalAddress = childEndpoint.getAddress();
447 return Preconditions.checkNotNull(physicalAddress, "Physical address not found " +
448 "in address endpoint: " + addressEp);
451 public boolean hasRelativeLocations(AddressEndpointWithLocation addedEp) {
452 return addedEp.getRelativeLocations() != null && addedEp.getRelativeLocations().getExternalLocation() != null;
455 public boolean isMetadataPort(AddressEndpointWithLocation addressEp) {
456 return hasRelativeLocations(addressEp) || IpAddressUtil.isMetadataIp(getInterfaceIp(addressEp));
459 public String getGatewayInterfaceName(String gwNamePrefix, String subnetUuid) {
460 return gwNamePrefix + subnetUuid;
463 public Routing getRouting(long vrf) {
464 return new RoutingBuilder().setIpv4VrfId(vrf).build();