| /* |
| * Copyright 2016-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.lisp.ctl.impl; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import org.onlab.packet.IpPrefix; |
| import org.onosproject.lisp.ctl.impl.map.ExpireMap; |
| import org.onosproject.lisp.ctl.impl.map.ExpireHashMap; |
| import org.onosproject.lisp.msg.protocols.DefaultLispProxyMapRecord.DefaultMapWithProxyBuilder; |
| import org.onosproject.lisp.msg.protocols.LispEidRecord; |
| import org.onosproject.lisp.msg.protocols.LispMapRecord; |
| import org.onosproject.lisp.msg.protocols.LispProxyMapRecord; |
| import org.onosproject.lisp.msg.types.LispAfiAddress; |
| |
| import java.util.List; |
| import java.util.Optional; |
| |
| /** |
| * A singleton class that stores EID-RLOC mapping information. |
| */ |
| public final class LispMappingDatabase { |
| |
| private static final long MINUTE_TO_MS_UNIT = 60 * 1000; |
| |
| private ExpireMap<LispEidRecord, LispProxyMapRecord> map = new ExpireHashMap<>(); |
| |
| /** |
| * Prevents object instantiation from external. |
| */ |
| private LispMappingDatabase() { |
| } |
| |
| /** |
| * Obtains a singleton instance. |
| * |
| * @return singleton instance |
| */ |
| public static LispMappingDatabase getInstance() { |
| return SingletonHelper.INSTANCE; |
| } |
| |
| /** |
| * Inserts a new EID-RLOC mapping record. |
| * |
| * @param eid endpoint identifier |
| * @param rloc route locator record |
| * @param proxyMapReply proxy map reply flag |
| */ |
| public void putMapRecord(LispEidRecord eid, LispMapRecord rloc, |
| boolean proxyMapReply) { |
| LispProxyMapRecord mapWithProxy = new DefaultMapWithProxyBuilder() |
| .withMapRecord(rloc) |
| .withIsProxyMapReply(proxyMapReply) |
| .build(); |
| map.put(eid, mapWithProxy, rloc.getRecordTtl() * MINUTE_TO_MS_UNIT); |
| } |
| |
| /** |
| * Returns the results whether a given EidRecord is contained in the map. |
| * |
| * @param eid endpoint identifier |
| * @return the results whether a given EidRecord is contained in the map |
| */ |
| public boolean hasEidRecord(LispEidRecord eid) { |
| return map.containsKey(eid); |
| } |
| |
| /** |
| * Removes an EID-RLOC mapping record with given endpoint identifier. |
| * |
| * @param eid endpoint identifier |
| */ |
| public void removeMapRecordByEid(LispEidRecord eid) { |
| map.remove(eid); |
| } |
| |
| /** |
| * Obtains all of the EID-RLOC mapping records. |
| * |
| * @return all of the EID-RLOC mapping records |
| */ |
| public List<LispMapRecord> getAllMapRecords() { |
| |
| List<LispMapRecord> mapRecords = Lists.newArrayList(); |
| |
| map.values().forEach(value -> mapRecords.add(value.getMapRecord())); |
| |
| return mapRecords; |
| } |
| |
| /** |
| * Obtains an EID-RLOC mapping record in accordance with the proxy map reply |
| * flag bit and EID record. |
| * |
| * @param eid endpoint identifier record |
| * @param proxyMapReply proxy map reply flag |
| * @return an EID-RLOC mapping record |
| */ |
| public LispMapRecord getMapRecordByEidRecord(LispEidRecord eid, boolean proxyMapReply) { |
| |
| for (LispEidRecord key : map.keySet()) { |
| if (isInRange(key, eid) && map.get(key) != null |
| && map.get(key).isProxyMapReply() == proxyMapReply) { |
| return map.get(key).getMapRecord(); |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Obtains a collection of EID-RLOC mapping record in accordance with the |
| * proxy map reply flag bit and EID record. |
| * |
| * @param eids endpoint identifier records |
| * @param proxyMapReply proxy map reply flag |
| * @return a collection of EID-RLOC mapping records |
| */ |
| public List<LispMapRecord> getMapRecordByEidRecords(List<LispEidRecord> eids, |
| boolean proxyMapReply) { |
| List<LispMapRecord> mapRecords = Lists.newArrayList(); |
| eids.forEach(eidRecord -> { |
| LispMapRecord mapRecord = getMapRecordByEidRecord(eidRecord, proxyMapReply); |
| if (mapRecord != null) { |
| mapRecords.add(mapRecord); |
| } |
| }); |
| return ImmutableList.copyOf(mapRecords); |
| } |
| |
| /** |
| * Obtains an EID-RLOC mapping record with given EID address. |
| * |
| * @param address endpoint identifier address |
| * @return an EID-RLOC mapping record |
| */ |
| public LispMapRecord getMapRecordByEidAddress(LispAfiAddress address) { |
| Optional<LispEidRecord> eidRecord = |
| map.keySet().stream().filter(k -> k.getPrefix().equals(address)).findFirst(); |
| return eidRecord.map(lispEidRecord -> |
| map.get(lispEidRecord).getMapRecord()).orElse(null); |
| } |
| |
| /** |
| * Generates CIDR style string from EID record. |
| * |
| * @param eidRecord EID record |
| * @return CIDR style string |
| */ |
| private String cidrfy(LispEidRecord eidRecord) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(eidRecord.getPrefix().toString()); |
| sb.append("/"); |
| sb.append(eidRecord.getMaskLength()); |
| return sb.toString(); |
| } |
| |
| /** |
| * Checks whether the EID record is included in the given EID record. |
| * |
| * @param origin the EID record to be compared |
| * @param compare the EID record to compare |
| * @return boolean result |
| */ |
| private boolean isInRange(LispEidRecord origin, LispEidRecord compare) { |
| |
| IpPrefix originIpPrefix = IpPrefix.valueOf(cidrfy(origin)); |
| IpPrefix compareIpPrefix = IpPrefix.valueOf(cidrfy(compare)); |
| |
| return originIpPrefix.contains(compareIpPrefix); |
| } |
| |
| /** |
| * Prevents object instantiation from external. |
| */ |
| private static final class SingletonHelper { |
| private static final String ILLEGAL_ACCESS_MSG = "Should not instantiate this class."; |
| private static final LispMappingDatabase INSTANCE = new LispMappingDatabase(); |
| |
| private SingletonHelper() { |
| throw new IllegalAccessError(ILLEGAL_ACCESS_MSG); |
| } |
| } |
| } |