2 * Copyright (c) 2016 Cisco Systems, Inc. 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
8 package org.opendaylight.lispflowmapping.southbound.lisp;
10 import java.util.List;
12 import java.util.concurrent.ConcurrentHashMap;
13 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
14 import org.opendaylight.lispflowmapping.mapcache.AuthKeyDb;
15 import org.opendaylight.mdsal.binding.api.DataBroker;
16 import org.opendaylight.mdsal.binding.api.DataObjectModification;
17 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
18 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
19 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
20 import org.opendaylight.mdsal.binding.api.DataTreeModification;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.map.register.cache.metadata.EidLispAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.map.register.cache.metadata.EidLispAddressKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingDatabase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKeyBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.VirtualNetworkIdentifier;
29 import org.opendaylight.yangtools.concepts.Registration;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * DataListener for all AuthenticationKey modification events.
38 public class AuthenticationKeyDataListener implements DataTreeChangeListener<AuthenticationKey> {
39 private static final Logger LOG = LoggerFactory.getLogger(AuthenticationKeyDataListener.class);
41 private final AuthKeyDb akdb;
42 private final InstanceIdentifier<AuthenticationKey> path;
43 private final Registration registration;
44 private final ConcurrentHashMap<Eid, Long> updatedEntries;
46 public AuthenticationKeyDataListener(final DataBroker broker, final AuthKeyDb akdb) {
48 path = InstanceIdentifier.create(MappingDatabase.class).child(VirtualNetworkIdentifier.class)
49 .child(AuthenticationKey.class);
50 LOG.trace("Registering AuthenticationKey listener.");
51 registration = broker.registerTreeChangeListener(
52 DataTreeIdentifier.of(LogicalDatastoreType.CONFIGURATION, path), this);
53 updatedEntries = new ConcurrentHashMap<>();
56 public void closeDataChangeListener() {
61 public synchronized void onDataTreeChanged(final List<DataTreeModification<AuthenticationKey>> changes) {
62 for (DataTreeModification<AuthenticationKey> change : changes) {
63 final DataObjectModification<AuthenticationKey> mod = change.getRootNode();
65 if (ModificationType.DELETE == mod.modificationType()) {
66 final AuthenticationKey authKey = mod.dataBefore();
68 LOG.trace("Received deleted data");
69 LOG.trace("Key: {}", change.getRootPath().path());
70 LOG.trace("Value: {}", authKey);
72 final AuthenticationKey convertedAuthKey = convertToBinaryIfNecessary(authKey);
74 akdb.removeAuthenticationKey(convertedAuthKey.getEid());
75 updatedEntries.put(convertedAuthKey.getEid(), System.currentTimeMillis());
76 } else if (ModificationType.WRITE == mod.modificationType()
77 || ModificationType.SUBTREE_MODIFIED == mod.modificationType()) {
78 if (ModificationType.WRITE == mod.modificationType()) {
79 LOG.trace("Received created data");
81 LOG.trace("Received updated data");
83 // Process newly created or updated authentication keys
84 final AuthenticationKey authKey = mod.dataAfter();
86 LOG.trace("Key: {}", change.getRootPath().path());
87 LOG.trace("Value: {}", authKey);
89 final AuthenticationKey convertedAuthKey = convertToBinaryIfNecessary(authKey);
91 akdb.addAuthenticationKey(convertedAuthKey.getEid(), convertedAuthKey.getMappingAuthkey());
92 updatedEntries.put(convertedAuthKey.getEid(), System.currentTimeMillis());
94 LOG.warn("Ignoring unhandled modification type {}", mod.modificationType());
100 * We maintain a HashMap with the update times of AuthenticationKey objects in the updatedEntries field. We keep
101 * entries in the HashMap for the Map-Register cache timeout interval, and lazy remove them afterwards. As a result
102 * the same EID will be considered updated during that interval, even on subsequent queries. This is necessary
103 * because more than one xTR may register the same EID, and to avoid complexity we don't store origin information.
104 * The performance trade-off is not significant, because during a typical cache timeout the same xTR will send only
105 * a few registration packets (2 for the default value of 90s, when UDP Map-Registers are sent at 1 minute
108 * @param eids List of EIDs to check
109 * @param timeout MapRegister cache timeout value
110 * @return false if any of the EIDs in the eids list was updated in the last timout period, true otherwise
112 public synchronized boolean authKeysForEidsUnchanged(final Map<EidLispAddressKey, EidLispAddress> eids,
113 final long timeout) {
114 boolean result = true;
115 Long currentTime = System.currentTimeMillis();
116 for (EidLispAddress eidLispAddress : eids.values()) {
117 Long updateTime = updatedEntries.get(eidLispAddress.getEid());
118 if (updateTime != null) {
120 if (currentTime - updateTime > timeout) {
121 updatedEntries.remove(eidLispAddress.getEid());
128 private static AuthenticationKey convertToBinaryIfNecessary(final AuthenticationKey authKey) {
129 Eid originalEid = authKey.getEid();
130 if (LispAddressUtil.addressNeedsConversionToBinary(originalEid.getAddress())) {
131 AuthenticationKeyBuilder akb = new AuthenticationKeyBuilder(authKey);
132 akb.setEid(LispAddressUtil.convertToBinary(originalEid));