package org.opendaylight.lispflowmapping.implementation;
+import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
import org.opendaylight.lispflowmapping.implementation.mapcache.FlatMapCache;
import org.opendaylight.lispflowmapping.implementation.mapcache.MultiTableMapCache;
import org.opendaylight.lispflowmapping.implementation.mapcache.SimpleMapCache;
import org.opendaylight.lispflowmapping.implementation.mdsal.DataStoreBackEnd;
+import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
+import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
import org.opendaylight.lispflowmapping.interfaces.mapcache.IMappingSystem;
import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
+import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
private IMapCache pmc;
private final EnumMap<MappingOrigin, IMapCache> tableMap = new EnumMap<>(MappingOrigin.class);
private DataStoreBackEnd dsbe;
- private BindingAwareBroker bindingAwareBroker;
public MappingSystem(ILispDAO dao, boolean iterateMask, boolean notifications, boolean overwrite) {
this.dao = dao;
}
public void addMapping(MappingOrigin origin, Eid key, Object value) {
- tableMap.get(origin).addMapping(key, value, overwrite);
+ tableMap.get(origin).addMapping(key, value, origin == MappingOrigin.Southbound ? overwrite : true);
}
public void updateMappingRegistration(MappingOrigin origin, Eid key) {
tableMap.get(origin).updateMappingRegistration(key);
}
+ private MappingRecord updateServicePathMappingRecord(MappingRecord mapping, Eid eid) {
+ // keep properties of original record
+ MappingRecordBuilder recordBuilder = new MappingRecordBuilder(mapping);
+ recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
+
+ // there should only be one locator record
+ if (mapping.getLocatorRecord().size() != 1) {
+ LOG.warn("MappingRecord associated to ServicePath EID has more than one locator!");
+ return mapping;
+ }
+
+ LocatorRecord locatorRecord = mapping.getLocatorRecord().get(0);
+ long serviceIndex = ((ServicePath) eid.getAddress()).getServicePath().getServiceIndex();
+ int index = LispAddressUtil.STARTING_SERVICE_INDEX - (int) serviceIndex;
+ Rloc rloc = locatorRecord.getRloc();
+ if (rloc.getAddress() instanceof Ipv4 || rloc.getAddress() instanceof Ipv6) {
+ if (index != 0) {
+ LOG.warn("Service Index should be 255 for simple IP RLOCs!");
+ }
+ return mapping;
+ } else if (rloc.getAddress() instanceof ExplicitLocatorPath) {
+ ExplicitLocatorPath elp = (ExplicitLocatorPath) rloc.getAddress();
+ List<Hop> hops = elp.getExplicitLocatorPath().getHop();
+
+ if (index < 0 || index > hops.size()) {
+ LOG.warn("Service Index out of bounds!");
+ return mapping;
+ }
+
+ SimpleAddress nextHop = hops.get(index).getAddress();
+ LocatorRecordBuilder lrb = new LocatorRecordBuilder(locatorRecord);
+ lrb.setRloc(LispAddressUtil.toRloc(nextHop));
+ recordBuilder.getLocatorRecord().add(lrb.build());
+ return recordBuilder.build();
+ } else {
+ LOG.warn("Nothing to do with ServicePath mapping record");
+ return mapping;
+ }
+ }
+
@Override
public Object getMapping(Eid src, Eid dst) {
- // NOTE: what follows is just a simple implementation of a lookup logic, it SHOULD be subject to future
- // improvements
+ // NOTE: Currently we have two lookup algorithms implemented, which are configurable
+ // using lookupPolicy in ConfigIni.java
+
+ if (ConfigIni.getInstance().getLookupPolicy() == ConfigIni.NB_AND_SB) {
+ return getMappingNbSbIntersection(src, dst);
+ } else {
+ return getMappingNbFirst(src, dst);
+ }
+ }
+
+ private Object getMappingNbFirst(Eid src, Eid dst) {
- // first lookup src/dst in policy table
- Object mapping = pmc.getMapping(src, dst);
+ // Default lookup policy is northboundFirst
+ //lookupPolicy == NB_FIRST
- // if nothing is found, lookup src/dst in sb table
- if (mapping == null) {
- return smc.getMapping(src, dst);
+ Object nbMapping = pmc.getMapping(src, dst);
+
+ if (nbMapping == null) {
+ return getSbMappingWithExpiration(src, dst);
+ }
+ if (dst.getAddress() instanceof ServicePath) {
+ return updateServicePathMappingRecord((MappingRecord) nbMapping, dst);
}
+ return nbMapping;
+ }
- return mapping;
+ private Object getMappingNbSbIntersection(Eid src, Eid dst) {
+ //lookupPolicy == NB_AND_SB, we return intersection
+ //of NB and SB mappings, or NB mapping if intersection is empty.
+
+ Object nbMapping = pmc.getMapping(src, dst);
+ if (nbMapping == null) {
+ return nbMapping;
+ }
+ // no intersection for Service Path mappings
+ if (dst.getAddress() instanceof ServicePath) {
+ return updateServicePathMappingRecord((MappingRecord)nbMapping, dst);
+ }
+ Object sbMapping = getSbMappingWithExpiration(src, dst);
+ if (sbMapping == null) {
+ return nbMapping;
+ }
+ // both NB and SB mappings exist. Compute intersection of the mappings
+ return MappingMergeUtil.computeNbSbIntersection((MappingRecord)nbMapping, (MappingRecord)sbMapping);
+ }
+
+ private Object getSbMappingWithExpiration(Eid src, Eid dst) {
+ Object mappingObject = smc.getMapping(src, dst);
+ if (mappingObject instanceof MappingRecord) {
+ MappingRecord mapping = (MappingRecord) mappingObject;
+ if (MappingMergeUtil.mappingIsExpired(mapping)) {
+ dsbe.removeMapping(DSBEInputUtil.toMapping(MappingOrigin.Southbound, mapping.getEid(),
+ new SiteId(mapping.getSiteId()), mapping));
+ return null;
+ }
+ }
+ return mappingObject;
}
@Override
@Override
public Object getMapping(MappingOrigin origin, Eid key) {
+ if (origin.equals(MappingOrigin.Southbound)) {
+ return getSbMappingWithExpiration(null, key);
+ }
return tableMap.get(origin).getMapping(null, key);
}
@Override
public void removeMapping(MappingOrigin origin, Eid key) {
- tableMap.get(origin).removeMapping(key, overwrite);
+ tableMap.get(origin).removeMapping(key, origin == MappingOrigin.Southbound ? overwrite : true);
if (notificationService) {
// TODO
}
@Override
public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
- LOG.debug("Adding authentication key '{}' for {}", key,
+ LOG.debug("Adding authentication key '{}' with key-ID {} for {}", authKey.getKeyString(), authKey.getKeyType(),
LispAddressStringifier.getString(key));
smc.addAuthenticationKey(key, authKey);
}
LOG.info("Restoring {} mappings and {} keys from datastore into DAO", mappings.size(), authKeys.size());
+ int expiredMappings = 0;
for (Mapping mapping : mappings) {
+ if (MappingMergeUtil.mappingIsExpired(mapping.getMappingRecord())) {
+ dsbe.removeMapping(mapping);
+ expiredMappings++;
+ continue;
+ }
addMapping(mapping.getOrigin(), mapping.getMappingRecord().getEid(), mapping.getMappingRecord());
}
+ LOG.info("{} mappings were expired and were not restored", expiredMappings);
for (AuthenticationKey authKey : authKeys) {
addAuthenticationKey(authKey.getEid(), authKey.getMappingAuthkey());