Fix Metadata Eid processing for LISP
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / util / ConfigManagerHelper.java
index b34e6c726428f4466234855b171a2f2a5e9d7519..67ad968dac4b06f685a929a355da9403a3794081 100644 (file)
@@ -12,18 +12,30 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispState;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.InterfaceUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
@@ -33,23 +45,25 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev14061
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLength;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.hmac.key.grouping.HmacKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev171013.HmacKeyType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev171013.dp.subtable.grouping.local.mappings.local.mapping.Eid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev171013.hmac.key.grouping.HmacKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
@@ -59,65 +73,19 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nonnull;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-
-/**
- * Created by Shakib Ahmed on 3/31/17.
- */
 public class ConfigManagerHelper {
     private static final Logger LOG = LoggerFactory.getLogger(ConfigManagerHelper.class);
 
-    private static final String TENANT_INTERFACE = "tenant-interface";
     private MountedDataBrokerProvider mountedDataBrokerProvider;
 
     public ConfigManagerHelper(MountedDataBrokerProvider mountedDataBrokerProvider) {
         this.mountedDataBrokerProvider = mountedDataBrokerProvider;
     }
 
-    public Optional<DataBroker> getPotentialExternalDataBroker(AddressEndpointWithLocation addressEpWithLoc) {
-        ExternalLocationCase externalLocationCase = resolveAndValidateLocation(addressEpWithLoc);
-        InstanceIdentifier<?> vppNodeIid = externalLocationCase.getExternalNodeMountPoint();
-        String interfacePath = externalLocationCase.getExternalNodeConnector();
-
-        Optional<DataBroker> potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
 
-        Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
-                "Cannot resolve data broker for interface path: {}", interfacePath);
-
-        return potentialVppDataProvider;
-    }
-
-    public Optional<DataBroker> getPotentialExternalDataBroker(VppEndpoint vppEp) {
-        InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(vppEp.getVppNodeId());
-        Optional<DataBroker> potentialVppDataProvider =
-                mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
-
-        Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
-                "Cannot resolve data broker for Vpp Endpoint: {}", vppEp);
-        return potentialVppDataProvider;
-    }
-
-    public Optional<DataBroker> getPotentialExternalDataBroker(String hostId) {
-        InstanceIdentifier<Node> nodeIid = VppIidFactory.getNetconfNodeIid(new NodeId(hostId));
-        Optional<DataBroker> potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(nodeIid);
-        Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
-                "Data Broker not found for {}", hostId);
-        return potentialVppDataProvider;
-    }
-
-    public Optional<String> getHostName(AddressEndpointWithLocation addrEp) {
-        ExternalLocationCase locationCase = resolveAndValidateLocation(addrEp);
-        NodeKey nodeKey = locationCase.getExternalNodeMountPoint().firstKeyOf(Node.class);
-        String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
-                "Host Id extraction failed from address endpoint: {}", addrEp);
-        return Optional.fromNullable(hostId);
-    }
-
-    public ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
+    public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
+        Preconditions.checkNotNull(addrEpWithLoc.getAbsoluteLocation(), "Absolute location for " +
+                "AddressEndpointWithLocation missing: " + addrEpWithLoc.toString() );
         LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
         if (!(locationType instanceof ExternalLocationCase)) {
             throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
@@ -131,12 +99,18 @@ public class ConfigManagerHelper {
     }
 
     //This is almost identical to VBD's equivalent method
-    public ListenableFuture<String> readRlocInterface(@Nonnull String hostName, @Nonnull DataBroker vppDataBroker) {
+    public ListenableFuture<String> getLispDataRlocInterfaceName(@Nonnull String hostName) {
         Preconditions.checkNotNull(hostName, "Hostname is null!");
-        Preconditions.checkNotNull(vppDataBroker, "Vpp DataBroker is null!");
-        final Optional<InterfacesState> opInterfaceState = GbpNetconfTransaction.read(vppDataBroker,
-                LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class),
-                GbpNetconfTransaction.RETRY_COUNT);
+
+        PhysicalInterfaces physicalInterfaces = HostRelatedInfoContainer.getInstance()
+                .getPhysicalInterfaceState(hostName);
+
+        String publicInterfaceName = physicalInterfaces == null ? "" : physicalInterfaces
+                .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
+
+        final Optional<InterfacesState> opInterfaceState =
+                GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.create(InterfacesState.class), GbpNetconfTransaction.RETRY_COUNT);
 
         if (!opInterfaceState.isPresent()) {
             LOG.debug("There appear to be no interfaces on node {}.", hostName);
@@ -152,19 +126,32 @@ public class ConfigManagerHelper {
         }
 
         final Optional<Interfaces> opInterfaces =
-                GbpNetconfTransaction.read(vppDataBroker, LogicalDatastoreType.CONFIGURATION,
+                GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.CONFIGURATION,
                         InstanceIdentifier.create(Interfaces.class), GbpNetconfTransaction.RETRY_COUNT);
 
 
         if (opInterfaces.isPresent()) {
+
+            List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
+                    interfaces.Interface> hostInterfaceFromOpDS = opInterfaces.get().getInterface();
+
             for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
-                    interfaces.Interface intf : opInterfaces.get().getInterface()) {
-                if (TENANT_INTERFACE.equals(intf.getDescription())
+                    interfaces.Interface intf : hostInterfaceFromOpDS) {
+                if (Constants.TENANT_INTERFACE.equals(intf.getDescription())
                         && ipAddressPresent(intf)
                         && intf.getType().equals(EthernetCsmacd.class)) {
                     return Futures.immediateFuture(intf.getName());
                 }
             }
+
+            for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
+                    interfaces.Interface intf : hostInterfaceFromOpDS) {
+                if (ipAddressPresent(intf)
+                        && intf.getType().equals(EthernetCsmacd.class)
+                        && !intf.getName().equalsIgnoreCase(publicInterfaceName)) {
+                    return Futures.immediateFuture(intf.getName());
+                }
+            }
         }
 
         if (interfaceName == null) {
@@ -197,6 +184,39 @@ public class ConfigManagerHelper {
         return ip != null;
     }
 
+    private String ipCidr(Interface intf) {
+        Interface2 augIntf = intf.getAugmentation(Interface2.class);
+
+        if (augIntf == null) {
+            return null;
+        }
+
+        Ipv4 ipv4 = augIntf.getIpv4();
+
+        if (ipv4 == null) {
+            return null;
+        }
+
+        final List<Address> addresses = ipv4.getAddress();
+
+        if (addresses == null || addresses.isEmpty()) {
+            return null;
+        }
+
+        Address firstAddress = addresses.get(0);
+        String ipString = firstAddress.getIp().getValue();
+        String length = "";
+        if (firstAddress.getSubnet().getImplementedInterface().equals(PrefixLength.class)) {
+            length = "" + ((PrefixLength)firstAddress.getSubnet()).getPrefixLength();
+        }
+
+        if (length.isEmpty()) {
+            return null;
+        }
+
+        return ipString + "/" + length;
+    }
+
     private boolean ipAddressPresent(final org.opendaylight.yang.gen.v1.urn.ietf.
             params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intf) {
         final Interface1 augIntf = intf.getAugmentation(Interface1.class);
@@ -222,12 +242,47 @@ public class ConfigManagerHelper {
         return ip != null;
     }
 
+    public String getLispCpRlocInterfaceName(@Nonnull String hostName) {
+        List<Interface> operationalInterfaceList =
+                InterfaceUtil.getOperationalInterfaces(LispUtil.HOSTNAME_TO_IID.apply(hostName));
+
+        if (operationalInterfaceList == null) {
+            return null;
+        } else {
+            int maxLen = -1;
+            String outgoingInterface = "";
+
+            for (Interface intf : operationalInterfaceList) {
+                String ipCidr = ipCidr(intf);
+
+                if (ipCidr == null) {
+                    continue;
+                }
+
+                if (IpAddressUtil.ipInRange(ConfigUtil.getInstance().getOdlIp().getIpv4Address(),
+                        IpAddressUtil.startIpOfSubnet(ipCidr), IpAddressUtil.endIpOfSubnet(ipCidr))) {
+                    int tmpLen = IpAddressUtil.maskLen(ipCidr);
+                    if (tmpLen > maxLen) {
+                        maxLen = tmpLen;
+                        outgoingInterface = intf.getName();
+                    }
+                }
+            }
+            return outgoingInterface;
+        }
+    }
+
     public String constructLocatorSetName(int locatorSetCount) {
         return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + (locatorSetCount + 1);
     }
 
-    public String constructMappingName(int presentMappingCount) {
-        return LispStateManager.DEFAULT_MAPPINGRECORD_NAME_PREFIX + (presentMappingCount + 1);
+    public String constructLocatorSetNameForItrRloc() {
+        return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + "_itr_rloc";
+    }
+
+    public String constructEidMappingName(AddressEndpointWithLocation addressEp, String interfaceName) {
+        String ipAddress = getInterfaceIp(addressEp).getValue();
+        return LispStateManager.DEFAULT_MAPPING_RECORD_NAME_PREFIX + interfaceName + "_" + ipAddress;
     }
 
     public String getSubnet(AddressEndpointWithLocation addressEp) {
@@ -245,7 +300,7 @@ public class ConfigManagerHelper {
         return LispUtil.toEid(LispUtil.toIpv4(ipPrefix), vni, Ipv4Afi.class);
     }
 
-    public String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
+    private static String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
         String ipPrefix = null;
         if (addressEp.getAddressType().equals(IpPrefixType.class)) {
             ipPrefix = addressEp.getAddress();
@@ -264,7 +319,7 @@ public class ConfigManagerHelper {
         return Preconditions.checkNotNull(ipPrefix, "No IP address found for Address Endpoint: {}", addressEp);
     }
 
-    public Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
+    public static Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
         String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
         return LispUtil.toIpv4(ipPrefix).getIpv4();
     }
@@ -295,6 +350,12 @@ public class ConfigManagerHelper {
         return VppPathMapper.interfacePathToInterfaceName(interfacePath);
     }
 
+    public Optional<String> getInterfaceName(ExternalLocation externalLocation) {
+        String interfacePath = externalLocation.getExternalNodeConnector();
+        return VppPathMapper.interfacePathToInterfaceName(interfacePath);
+    }
+
+
     public HmacKey getDefaultHmacKey() {
         return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
     }
@@ -317,6 +378,18 @@ public class ConfigManagerHelper {
                 "in address endpoint: " + addressEp);
     }
 
+    public boolean hasRelativeLocations(AddressEndpointWithLocation addedEp) {
+        return addedEp.getRelativeLocations() != null && addedEp.getRelativeLocations().getExternalLocation() != null;
+    }
+
+    public static boolean isMetadataPort(AddressEndpointWithLocation addressEp) {
+        return IpAddressUtil.isMetadataIp(getInterfaceIp(addressEp));
+    }
+
+    public String getGatewayInterfaceName(String gwNamePrefix, String subnetUuid) {
+        return gwNamePrefix + subnetUuid;
+    }
+
     public Routing getRouting(long vrf) {
         return new RoutingBuilder().setIpv4VrfId(vrf).build();
     }