import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Map;
+import java.util.Set;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
public interface ILispDAO {
*/
Eid getWidestNegativePrefix(Eid key);
+ /**
+ * Get the subtree of the given prefix.
+ *
+ * @param key
+ * The eid prefix, IPv4 or IPv6, to be looked up. Key must be normalized.
+ * @return The set of EIDs that part of the subtree of the given EID.
+ */
+ Set<Eid> getSubtree(Eid key);
+
/**
* Enumerate all the entries from the DAO.
*
package org.opendaylight.lispflowmapping.interfaces.mapcache;
+import java.util.Set;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
/**
*/
Eid getWidestNegativeMapping(Eid key);
+ /**
+ * Retrieves the subtree of a prefix.
+ *
+ * @param key
+ * Key to be looked up
+ * @return The set of prefixes in the subtree for the prefix
+ */
+ Set<Eid> getSubtree(Eid key);
+
/**
* Remove mapping.
*
package org.opendaylight.lispflowmapping.inmemorydb;
import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.lispflowmapping.inmemorydb.radixtrie.RadixTrie;
break;
}
if (node != null) {
- return LispAddressUtil.asIpv4PrefixBinaryEid(key, node.prefix(), (short) node.prefixLength());
+ return LispAddressUtil.asIpv4PrefixBinaryEid(
+ key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength());
}
} else if (key.getAddress() instanceof Ipv6PrefixBinary) {
Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) key.getAddress();
break;
}
if (node != null) {
- return LispAddressUtil.asIpv6PrefixBinaryEid(key, node.prefix(), (short) node.prefixLength());
+ return LispAddressUtil.asIpv6PrefixBinaryEid(
+ key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength());
}
}
return null;
return getPrefix(key, GetPrefixMethods.WIDEST_NEGATIVE);
}
+ @Override
+ public Set<Eid> getSubtree(Eid key) {
+ Set<RadixTrie<Object>.TrieNode> nodes = null;
+ if (key.getAddress() instanceof Ipv4PrefixBinary) {
+ Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) key.getAddress();
+ nodes = ip4Trie.lookupSubtree(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength());
+ } else if (key.getAddress() instanceof Ipv6PrefixBinary) {
+ Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) key.getAddress();
+ nodes = ip6Trie.lookupSubtree(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength());
+ }
+ return nodesToEids(key, nodes);
+ }
+
+ private static Set<Eid> nodesToEids(Eid key, Set<RadixTrie<Object>.TrieNode> nodes) {
+ if (nodes == null || nodes.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ Set<Eid> children = new HashSet<>();
+ for (RadixTrie<Object>.TrieNode node : nodes) {
+ if (key.getAddress() instanceof Ipv4PrefixBinary) {
+ children.add(LispAddressUtil.asIpv4PrefixBinaryEid(
+ key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength()));
+ } else if (key.getAddress() instanceof Ipv6PrefixBinary) {
+ children.add(LispAddressUtil.asIpv6PrefixBinaryEid(
+ key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength()));
+ }
+ }
+ return children;
+ }
+
private void tryRemoveFromTrie(Object key) {
if (key instanceof Eid) {
Eid eid = (Eid) key;
import java.net.UnknownHostException;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Deque;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.ListIterator;
+import java.util.Set;
/**
* Radix trie/tree (also known as Patricia tree) implementation. Supports CRD operations for
return null;
}
+ /**
+ * Return the subtree for a prefix, including the prefix itself if present, excluding virtual nodes.
+ *
+ * @param prefix Big endian byte array representation of the prefix to be looked up.
+ * @param preflen Prefix length
+ * @return Subtree from the prefix
+ */
+ public Set<TrieNode> lookupSubtree(byte[] prefix, int preflen) {
+ if (root == null || preflen > maxBits) {
+ return Collections.emptySet();
+ }
+
+ TrieNode node = root.findClosest(prefix, preflen);
+
+ // if no node is found or if node not a prefix
+ if (node == null || node.prefix == null) {
+ return Collections.emptySet();
+ }
+
+ Set<TrieNode> children = new HashSet<>();
+ children.add(node);
+ Iterator<TrieNode> it = node.iterator();
+ while (it.hasNext()) {
+ node = it.next();
+ if (node.prefix != null) {
+ children.add(node);
+ }
+ }
+
+ return children;
+ }
/**
* Remove prefix from radix trie.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.Set;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
assertTrue(res.prefixLength() == 2);
}
+ @Test
+ public void testIpv4ChildrenLookup() {
+ radixTrie4 = new RadixTrie<>(32, true);
+
+ addIp4Addresses(radixTrie4);
+ Set<RadixTrie<Integer>.TrieNode> res = radixTrie4.lookupSubtree(IP4_BYTES4, 24);
+ assertEquals(3, res.size());
+
+ radixTrie4 = new RadixTrie<>(32, true);
+
+ radixTrie4.insert(IP4_BYTES4, 24, 1);
+ res = radixTrie4.lookupSubtree(IP4_BYTES1, 16);
+ assertEquals(1, res.size());
+ }
+
/**
* Tests v6 CRD operations.
* It just makes sure v6 prefix lengths don't generate problems. Therefore it's not as thorough as v4.
}
private void addIp4Addresses(RadixTrie<Integer> trie) {
+ // 192.168.1.1/32
trie.insert(IP4_BYTES7, 32, 7);
+
+ // 192.168.1.0/25
trie.insert(IP4_BYTES6, 25, 6);
+
+ // 192.168.2.0/24
trie.insert(IP4_BYTES5, 24, 5);
+
+ // 192.168.1.0/24
trie.insert(IP4_BYTES4, 24, 4);
+
+ // 192.169.0.0/16
trie.insert(IP4_BYTES3, 16, 3);
+
+ // 192.167.0.0/16
trie.insert(IP4_BYTES2, 16, 2);
+
+ // 192.168.0.0/16
trie.insert(IP4_BYTES1, 16, 1);
}
}
public static Eid asIpv4PrefixBinaryEid(Eid eid, byte[] address, short mask) {
+ return asIpv4PrefixBinaryEid(eid.getVirtualNetworkId(), address, mask);
+ }
+
+ public static Eid asIpv4PrefixBinaryEid(long vni, byte[] address, short mask) {
+ return asIpv4PrefixBinaryEid(new InstanceIdType(vni), address, mask);
+ }
+
+ public static Eid asIpv4PrefixBinaryEid(InstanceIdType vni, byte[] address, short mask) {
Preconditions.checkArgument(address.length == 4,
"asIpv4PrefixBinaryEid called with incorrect length byte array ({})", address.length);
EidBuilder builder = new EidBuilder();
builder.setAddressType(Ipv4PrefixBinaryAfi.class);
- builder.setVirtualNetworkId(eid.getVirtualNetworkId());
+ builder.setVirtualNetworkId(vni);
builder.setAddress(new Ipv4PrefixBinaryBuilder().setIpv4AddressBinary(new Ipv4AddressBinary(address))
.setIpv4MaskLength(mask).build());
return builder.build();
}
public static Eid asIpv6PrefixBinaryEid(Eid eid, byte[] address, short mask) {
+ return asIpv6PrefixBinaryEid(eid.getVirtualNetworkId(), address, mask);
+ }
+
+ public static Eid asIpv6PrefixBinaryEid(long vni, byte[] address, short mask) {
+ return asIpv6PrefixBinaryEid(new InstanceIdType(vni), address, mask);
+ }
+
+ public static Eid asIpv6PrefixBinaryEid(InstanceIdType vni, byte[] address, short mask) {
Preconditions.checkArgument(address.length == 16,
"asIpv6PrefixBinaryEid called with incorrect length byte array ({})", address.length);
EidBuilder builder = new EidBuilder();
builder.setAddressType(Ipv6PrefixBinaryAfi.class);
- builder.setVirtualNetworkId(eid.getVirtualNetworkId());
+ builder.setVirtualNetworkId(vni);
builder.setAddress(new Ipv6PrefixBinaryBuilder().setIpv6AddressBinary(new Ipv6AddressBinary(address))
.setIpv6MaskLength(mask).build());
return builder.build();
package org.opendaylight.lispflowmapping.mapcache;
+import java.util.Collections;
+import java.util.Set;
import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
return null;
}
+ @Override
+ public Set<Eid> getSubtree(Eid key) {
+ return Collections.emptySet();
+ }
+
@Override
public void removeMapping(Eid eid) {
Eid key = MaskUtil.normalize(eid);
*/
package org.opendaylight.lispflowmapping.mapcache;
+import java.util.Collections;
import java.util.Map;
+import java.util.Set;
import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
return table.getWidestNegativePrefix(key);
}
+ @Override
+ public Set<Eid> getSubtree(Eid key) {
+ ILispDAO table = getVniTable(key);
+ if (table == null) {
+ return Collections.emptySet();
+ }
+ return table.getSubtree(key);
+ }
+
public void removeMapping(Eid eid) {
Eid key = MaskUtil.normalize(eid);
ILispDAO table = getVniTable(key);
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;
return table.getVirtualParentSiblingPrefix(MaskUtil.normalize(eid));
}
+ @Override
+ public Set<Eid> getSubtree(Eid eid) {
+ ILispDAO table = getVniTable(eid);
+ if (table == null) {
+ return Collections.emptySet();
+ }
+ return table.getSubtree(eid);
+ }
+
@Override
public void removeMapping(Eid eid) {
ILispDAO table = getVniTable(eid);