Bug 9116: SMR children of a prefix too
[lispflowmapping.git] / mappingservice / mapcache / src / main / java / org / opendaylight / lispflowmapping / mapcache / SimpleMapCache.java
index a2e88fcf4245c044651c351854e654b65c16a2c9..4310e35cbd438c47b3a1ab9fad12bc1c38020965 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -10,6 +10,8 @@ package org.opendaylight.lispflowmapping.mapcache;
 
 import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -19,13 +21,10 @@ import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
 import org.opendaylight.lispflowmapping.interfaces.mapcache.ILispMapCache;
 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
+import org.opendaylight.lispflowmapping.mapcache.lisp.LispMapCacheStringifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
 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.mapping.authkey.container.MappingAuthkey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Simple map-cache that works with 'simple' addresses (see lisp-proto.yang). It can do longest prefix matching for IP
@@ -36,30 +35,30 @@ import org.slf4j.LoggerFactory;
  *
  */
 public class SimpleMapCache implements ILispMapCache {
-    private static final Logger LOG = LoggerFactory.getLogger(SimpleMapCache.class);
     private ILispDAO dao;
 
     public SimpleMapCache(ILispDAO dao) {
         this.dao = dao;
     }
 
-    private ILispDAO getVniTable(Eid eid) {
-        long vni = 0;
+    private long getVni(Eid eid) {
         if (eid.getVirtualNetworkId() == null) {
-            vni = 0;
+            return 0;
         } else {
-            vni = eid.getVirtualNetworkId().getValue();
+            return eid.getVirtualNetworkId().getValue();
         }
-        return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
+    }
+
+    private ILispDAO getVniTable(Eid eid) {
+        return (ILispDAO) dao.getSpecific(getVni(eid), SubKeys.VNI);
+    }
+
+    private void removeVniTable(Eid eid) {
+        dao.removeSpecific(getVni(eid), SubKeys.VNI);
     }
 
     private ILispDAO getOrInstantiateVniTable(Eid eid) {
-        long vni = 0;
-        if (eid.getVirtualNetworkId() == null) {
-            vni = 0;
-        } else {
-            vni = eid.getVirtualNetworkId().getValue();
-        }
+        long vni = getVni(eid);
         ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
         if (table == null) {
             table = dao.putNestedTable(vni, SubKeys.VNI);
@@ -67,14 +66,10 @@ public class SimpleMapCache implements ILispMapCache {
         return table;
     }
 
-    private ILispDAO getXtrIdTable(Eid eid, ILispDAO dao) {
-        return (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
-    }
-
-    private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO dao) {
-        ILispDAO table = (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
+    private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO lispDAO) {
+        ILispDAO table = (ILispDAO) lispDAO.getSpecific(eid, SubKeys.XTRID_RECORDS);
         if (table == null) {
-            table = dao.putNestedTable(eid, SubKeys.XTRID_RECORDS);
+            table = lispDAO.putNestedTable(eid, SubKeys.XTRID_RECORDS);
         }
         return table;
     }
@@ -104,8 +99,8 @@ public class SimpleMapCache implements ILispMapCache {
 
     // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
     // address
-    private Object getMappingLpmEid(Eid eid, XtrId xtrId, ILispDAO dao) {
-        SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = dao.getBestPair(MaskUtil.normalize(eid));
+    private Object getMappingLpmEid(Eid eid, XtrId xtrId, ILispDAO lispDAO) {
+        SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = lispDAO.getBestPair(MaskUtil.normalize(eid));
         if (daoEntry != null) {
             if (xtrId != null) {
                 ILispDAO xtrIdTable = (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS);
@@ -139,10 +134,10 @@ public class SimpleMapCache implements ILispMapCache {
     }
 
     // Returns the list of mappings stored in an xTR-ID DAO
-    private List<Object> getXtrIdMappingList(ILispDAO dao) {
-        if (dao != null) {
+    private List<Object> getXtrIdMappingList(ILispDAO lispDAO) {
+        if (lispDAO != null) {
             final List<Object> records = new ArrayList<>();
-            dao.getAll(new IRowVisitor() {
+            lispDAO.getAll(new IRowVisitor() {
                 public void visitRow(Object keyId, String valueKey, Object value) {
                     if (valueKey.equals(SubKeys.RECORD)) {
                         records.add(value);
@@ -170,118 +165,113 @@ public class SimpleMapCache implements ILispMapCache {
         return null;
     }
 
+    // Returns null for positive mappings, and 0/0 for empty cache.
+    @Override
     public Eid getWidestNegativeMapping(Eid eid) {
         ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return null;
+            return MaskUtil.normalize(eid, (short) 0);
         }
         return table.getWidestNegativePrefix(MaskUtil.normalize(eid));
     }
 
     @Override
-    public void removeMapping(Eid eid) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+    public Eid getCoveringLessSpecific(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return;
+            return null;
         }
-
-        // We intentionally don't remove subscribers, so in case a mapping is re-added, they get notified
-        table.removeSpecific(key, SubKeys.RECORD);
-        table.removeSpecific(key, SubKeys.SRC_RLOCS);
-        table.removeSpecific(key, SubKeys.XTRID_RECORDS);
+        return table.getCoveringLessSpecific(MaskUtil.normalize(eid));
     }
 
     @Override
-    public void removeMapping(Eid eid, XtrId xtrId) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+    public Eid getParentPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return;
-        }
-        ILispDAO xtrIdTable = getXtrIdTable(key, table);
-        if (xtrIdTable == null) {
-            return;
+            return null;
         }
-        xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
+        return table.getParentPrefix(MaskUtil.normalize(eid));
     }
 
     @Override
-    public void removeXtrIdMappings(Eid eid, List<XtrId> xtrIds) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+    public Eid getSiblingPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return;
-        }
-        ILispDAO xtrIdTable = getXtrIdTable(key, table);
-        if (xtrIdTable == null) {
-            return;
-        }
-        for (XtrId xtrId : xtrIds) {
-            xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
+            return null;
         }
+        return table.getSiblingPrefix(MaskUtil.normalize(eid));
     }
 
     @Override
-    public void addAuthenticationKey(Eid eid, MappingAuthkey authKey) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getOrInstantiateVniTable(key);
-        table.put(key, new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
+    public Eid getVirtualParentSiblingPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return null;
+        }
+        return table.getVirtualParentSiblingPrefix(MaskUtil.normalize(eid));
     }
 
-    private MappingAuthkey getAuthKeyLpm(Eid prefix, ILispDAO db) {
-        short maskLength = MaskUtil.getMaskForAddress(prefix.getAddress());
-        while (maskLength >= 0) {
-            Eid key = MaskUtil.normalize(prefix, maskLength);
-            Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
-            if (password != null && password instanceof MappingAuthkey) {
-                return (MappingAuthkey) password;
-            }
-            maskLength -= 1;
+    @Override
+    public Set<Eid> getSubtree(Eid eid) {
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return Collections.emptySet();
         }
-        return null;
+        return table.getSubtree(eid);
     }
 
     @Override
-    public MappingAuthkey getAuthenticationKey(Eid eid) {
+    public void removeMapping(Eid eid) {
         ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return null;
+            return;
         }
-        if (MaskUtil.isMaskable(eid.getAddress()) && !(eid.getAddress() instanceof SourceDestKey)) {
-            return getAuthKeyLpm(eid, table);
-        } else {
-            Eid key = MaskUtil.normalize(eid);
-            Object password = table.getSpecific(key, SubKeys.AUTH_KEY);
-            if (password != null && password instanceof MappingAuthkey) {
-                return (MappingAuthkey) password;
-            } else {
-                LOG.warn("Failed to find password!");
-                return null;
-            }
+
+        Eid key = MaskUtil.normalize(eid);
+        table.remove(key);
+        if (table.isEmpty()) {
+            removeVniTable(eid);
         }
     }
 
     @Override
-    public void removeAuthenticationKey(Eid eid) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+    public void removeMapping(Eid eid, XtrId xtrId) {
+        List<XtrId> xtrIds = Arrays.asList(xtrId);
+        removeXtrIdMappings(eid, xtrIds);
+    }
+
+    @Override
+    public void removeXtrIdMappings(Eid eid, List<XtrId> xtrIds) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
-        table.removeSpecific(key, SubKeys.AUTH_KEY);
+        Eid key = MaskUtil.normalize(eid);
+        ILispDAO xtrIdTable = (ILispDAO) table.getSpecific(key, SubKeys.XTRID_RECORDS);
+        if (xtrIdTable == null) {
+            return;
+        }
+        for (XtrId xtrId : xtrIds) {
+            xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
+        }
+        if (xtrIdTable.isEmpty()) {
+            table.removeSpecific(key, SubKeys.XTRID_RECORDS);
+            if (table.isEmpty()) {
+                removeVniTable(eid);
+            }
+        }
     }
 
     @Override
     public void addData(Eid eid, String subKey, Object data) {
+        ILispDAO table = getOrInstantiateVniTable(eid);
         Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getOrInstantiateVniTable(key);
         table.put(key, new MappingEntry<>(subKey, data));
     }
 
     @Override
     public Object getData(Eid eid, String subKey) {
-        ILispDAO table = getOrInstantiateVniTable(eid);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return null;
         }
@@ -291,51 +281,24 @@ public class SimpleMapCache implements ILispMapCache {
 
     @Override
     public void removeData(Eid eid, String subKey) {
-        ILispDAO table = getOrInstantiateVniTable(eid);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
         Eid key = MaskUtil.normalize(eid);
         table.removeSpecific(key, subKey);
+        if (table.isEmpty()) {
+            removeVniTable(eid);
+        }
     }
 
     @Override
     public String printMappings() {
-        final StringBuffer sb = new StringBuffer();
-        sb.append("Keys\tValues\n");
-
-        final IRowVisitor innerVisitor = (new IRowVisitor() {
-            String lastKey = "";
-
-            public void visitRow(Object keyId, String valueKey, Object value) {
-                String key = keyId.getClass().getSimpleName() + "#" + keyId;
-                if (!lastKey.equals(key)) {
-                    sb.append("\n" + key + "\t");
-                }
-                sb.append(valueKey + "=" + value + "\t");
-                lastKey = key;
-            }
-        });
-
-        dao.getAll(new IRowVisitor() {
-            String lastKey = "";
+        return LispMapCacheStringifier.printSMCMappings(dao);
+    }
 
-            public void visitRow(Object keyId, String valueKey, Object value) {
-                String key = keyId.getClass().getSimpleName() + "#" + keyId;
-                if (!lastKey.equals(key)) {
-                    sb.append("\n" + key + "\t");
-                }
-                if (valueKey.equals(SubKeys.VNI)) {
-                    sb.append(valueKey + "= { ");
-                    ((ILispDAO)value).getAll(innerVisitor);
-                    sb.append("}\t");
-                } else {
-                    sb.append(valueKey + "=" + value + "\t");
-                }
-                lastKey = key;
-            }
-        });
-        sb.append("\n");
-        return sb.toString();
+    @Override
+    public String prettyPrintMappings() {
+        return LispMapCacheStringifier.prettyPrintSMCMappings(dao);
     }
 }