aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/map/lpm.c
blob: c0e5bad1417d7570a23a94ccd35486ad2240b44a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * Copyright (c) 2018 Cisco and/or its affiliates.
 * 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.
 */

#include "lpm.h"
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
#include <arpa/inet.h>
#include <vnet/ip/format.h>

static uint32_t
masked_address32 (uint32_t addr, uint8_t len)
{
  u32 a = ntohl(addr);
  return htonl(len == 32 ? a : a & ~(~0u >> len));
}
static uint64_t
masked_address64 (uint64_t addr, uint8_t len)
{
  return len == 64 ? addr : addr & ~(~0ull >> len);
}

static void
lpm_32_add (lpm_t *lpm, void *addr_v, u8 pfxlen,
	    u32 value)
{
  uword * hash, * result;
  u32 key;
  ip4_address_t *addr = addr_v;
  key = masked_address32(addr->data_u32, pfxlen);
  hash = lpm->hash[pfxlen];
  result = hash_get (hash, key);
  if (result) /* Entry exists */
    clib_warning("%U/%d already exists in table for domain %d",
		 format_ip4_address, addr, pfxlen, result[0]);

  /*
   * adding a new entry
   */
  if (hash == NULL) {
    hash = hash_create (32 /* elts */, sizeof (uword));
    hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK);
  }
  hash = hash_set(hash, key, value);
  lpm->hash[pfxlen] = hash;
}

static void
lpm_32_delete (lpm_t *lpm, void *addr_v, u8 pfxlen)
{
  uword * hash, * result;
  u32 key;
  ip4_address_t *addr = addr_v;
  key = masked_address32(addr->data_u32, pfxlen);
  hash = lpm->hash[pfxlen];
  result = hash_get (hash, key);
  if (result)
    hash_unset(hash, key);
  lpm->hash[pfxlen] = hash;
}

static u32
lpm_32_lookup (lpm_t *lpm, void *addr_v, u8 pfxlen)
{
  uword * hash, * result;
  i32 mask_len;
  u32 key;
  ip4_address_t *addr = addr_v;
  for (mask_len = pfxlen; mask_len >= 0; mask_len--) {
    hash = lpm->hash[mask_len];
    if (hash) {
      key = masked_address32(addr->data_u32, mask_len);
      result = hash_get (hash, key);
      if (result != NULL) {
	return (result[0]);
      }
    }
  }
  return (~0);
}

static int
lpm_128_lookup_core (lpm_t *lpm, ip6_address_t *addr, u8 pfxlen, u32 *value)
{
  BVT(clib_bihash_kv) kv, v;
  int rv;
  kv.key[0] = masked_address64(addr->as_u64[0], pfxlen > 64 ? 64 : pfxlen);
  kv.key[1] = masked_address64(addr->as_u64[1], pfxlen > 64 ? pfxlen - 64 : 0);
  kv.key[2] = pfxlen;
  rv = BV(clib_bihash_search_inline_2)(&lpm->bihash, &kv, &v);
  if (rv != 0)
    return -1;
  *value = v.value;
  return 0;
}

static u32
lpm_128_lookup (lpm_t *lpm, void *addr_v, u8 pfxlen)
{
  ip6_address_t *addr = addr_v;
  int i = 0, rv;
  u32 value;
  clib_bitmap_foreach (i, lpm->prefix_lengths_bitmap)
     {
      rv = lpm_128_lookup_core(lpm, addr, i, &value);
      if (rv == 0)
	return value;
    }
  return ~0;
}

static void
lpm_128_add (lpm_t *lpm, void *addr_v, u8 pfxlen, u32 value)
{
  BVT(clib_bihash_kv) kv;
  ip6_address_t *addr = addr_v;

  kv.key[0] = masked_address64(addr->as_u64[0], pfxlen > 64 ? 64 : pfxlen);
  kv.key[1] = masked_address64(addr->as_u64[1], pfxlen > 64 ? pfxlen - 64 : 0);
  kv.key[2] = pfxlen;
  kv.value = value;
  BV(clib_bihash_add_del)(&lpm->bihash, &kv, 1);
  lpm->prefix_length_refcount[pfxlen]++;
  lpm->prefix_lengths_bitmap = clib_bitmap_set (lpm->prefix_lengths_bitmap, 128 - pfxlen, 1);
}

static void
lpm_128_delete (lpm_t *lpm, void *addr_v, u8 pfxlen)
{
  ip6_address_t *addr = addr_v;
  BVT(clib_bihash_kv) kv;
  kv.key[0] = masked_address64(addr->as_u64[0], pfxlen > 64 ? 64 : pfxlen);
  kv.key[1] = masked_address64(addr->as_u64[1], pfxlen > 64 ? pfxlen - 64 : 0);
  kv.key[2] = pfxlen;
  BV(clib_bihash_add_del)(&lpm->bihash, &kv, 0);

  /* refcount accounting */
  ASSERT (lpm->prefix_length_refcount[pfxlen] > 0);
  if (--lpm->prefix_length_refcount[pfxlen] == 0) {
    lpm->prefix_lengths_bitmap = clib_bitmap_set (lpm->prefix_lengths_bitmap, 
						  128 - pfxlen, 0);
  }
}

lpm_t *
lpm_table_init (enum lpm_type_e lpm_type)
{
  lpm_t * lpm = clib_mem_alloc(sizeof(*lpm));
  memset(lpm, 0, sizeof(*lpm));

  switch (lpm_type) {
  case LPM_TYPE_KEY32:
    lpm->add = lpm_32_add;
    lpm->delete = lpm_32_delete;
    lpm->lookup = lpm_32_lookup;
    break;
  case LPM_TYPE_KEY128:
    lpm->add = lpm_128_add;
    lpm->delete = lpm_128_delete;
    lpm->lookup = lpm_128_lookup;
    /* Make bihash sizes configurable */
    BV (clib_bihash_init) (&(lpm->bihash),
			   "LPM 128", 64*1024, 32<<20);

    break;
  default:
    ASSERT(0);
  }
  return lpm;
}
endaylight.controller</groupId> <artifactId>mdsal-artifacts</artifactId> <version>${odl.mdsal.controller.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.opendaylight.mdsal</groupId> <artifactId>mdsal-artifacts</artifactId> <version>${odl.mdsal.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.opendaylight.netconf</groupId> <artifactId>netconf-artifacts</artifactId> <version>${odl.netconf.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.opendaylight.netconf</groupId> <artifactId>restconf-artifacts</artifactId> <version>${odl.restconf.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.opendaylight.mdsal.model</groupId> <artifactId>mdsal-model-artifacts</artifactId> <version>${odl.mdsalmodel.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.opendaylight.bgpcep</groupId> <artifactId>bgpcep-artifacts</artifactId> <version>${odl.bgpcep.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Utilities --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> </dependency> <dependency> <groupId>com.google.code.findbugs</groupId> <artifactId>jsr305</artifactId> <version>${jsr305.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.annotation</artifactId> <version>${jdt.version}</version> </dependency> <!-- Testing Dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Dont use mockito-all, it has problematic dependency on harmcrest More details here - https://github.com/mockito/mockito/issues/324--> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>${mockito.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-all</artifactId> <version>${hamcrest.version}</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement> <plugins> <!-- checkstyle --> <plugin> <artifactId>maven-checkstyle-plugin</artifactId> <version>${checkstyle.plugin.version}</version> <configuration> <!--TODO HONEYCOMB-155 enable fail on violation after issues are resolved + set in as errors in checkstyle xml--> <failOnViolation>false</failOnViolation> <failsOnError>true</failsOnError> <consoleOutput>true</consoleOutput> <includeTestResources>true</includeTestResources> <includeTestSourceDirectory>true</includeTestSourceDirectory> <includes>**\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat,**\/*.yang</includes> <excludes>**\/target\/, **\/bin\/, **\/target-ide\/, **\/src/main/yang-gen-config\/, org/opendaylight/yang/gen/**, **\/src/main/yang-gen-sal\/, **\/src/main/xtend-gen\/, **\/src/main/yang\/, **\/archetype-resources\/, **\/.idea\/</excludes> </configuration> <executions> <!-- Override license check configuration to fit Honeycomb coding style--> <execution> <id>check-license</id> <goals> <goal>check</goal> </goals> <phase>process-sources</phase> <configuration> <configLocation>honeycomb-checkstyle-license.xml</configLocation> <outputFile>${project.build.directory}/checkstyle-license-result.xml</outputFile> </configuration> </execution> <!-- Add logging checks from yangtools --> <execution> <id>check-logging</id> <goals> <goal>check</goal> </goals> <phase>process-sources</phase> <configuration> <configLocation>honeycomb-checkstyle-logging.xml</configLocation> <sourceDirectories> <sourceDirectory>${project.basedir}</sourceDirectory> </sourceDirectories> <outputFile>${project.build.directory}/checkstyle-logging-result.xml</outputFile> </configuration> </execution> <!-- Check HC's coding style --> <execution> <goals> <goal>check</goal> </goals> <phase>process-sources</phase> <configuration> <configLocation>honeycomb-checkstyle.xml</configLocation> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>io.fd.honeycomb.common</groupId> <artifactId>honeycomb-checkstyle</artifactId> <!-- Hardcoded version to prevent archetype generated projects to use their own project version --> <version>1.19.04-SNAPSHOT</version> </dependency> <!-- Necessary for logging checks --> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>checkstyle-logging</artifactId> <version>${odl.yangtools.version}</version> </dependency> <!-- Needed by ODL's checkstyle-logging --> <dependency> <groupId>com.puppycrawl.tools</groupId> <artifactId>checkstyle</artifactId> <version>${checkstyle.version}</version> </dependency> </dependencies> </plugin> <!-- Deactivate strict java8 checks --> <!-- TODO HONEYCOMB-156 fix all the javadoc offenders of doclint --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>${maven.javadoc.version}</version> <configuration> <additionalparam>-Xdoclint:none</additionalparam> </configuration> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <!-- Sonar --> <!-- If Maven encounters a plugin with no version declaration, it will use the LATEST version. which might not be compatible with Sonar server (fd.io uses 6.7.3 currently). Therefore it is recommended to lock down version of Sonar plugin: http://blog.sonatype.com/2008/04/maven-209-released/ --> <plugin> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>3.4.1.1170</version> </plugin> <!-- jacoco test coverage for sonar --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.version}</version> <executions> <execution> <id>agent-for-ut</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>agent-for-it</id> <goals> <goal>prepare-agent-integration</goal> </goals> </execution> <execution> <id>jacoco-site</id> <goals> <goal>report</goal> </goals> </execution> </executions> <configuration> <!-- Appends data to existing JaCoCo execution file. Required for IT coverage. Will not affect UT which use separate files. --> <append>true</append> <excludes> <exclude>**/gen/**</exclude> <exclude>**/generated-sources/**</exclude> <exclude>**/yang-gen/**</exclude> </excludes> </configuration> </plugin> <!-- Enforce maven version --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>${enforcer.version}</version> <executions> <execution> <id>enforce-maven</id> <configuration> <rules> <requireMavenVersion> <version>3.1.1</version> </requireMavenVersion> </rules> </configuration> <goals> <goal>enforce</goal> </goals> </execution> </executions> </plugin> <!-- Compile with google static analysis tool: error_prone --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compile.plugin.version}</version> <configuration> <!-- Use google's error-prone static analysis--> <compilerId>javac-with-errorprone</compilerId> <forceJavacCompilerUse>true</forceJavacCompilerUse> <showWarnings>true</showWarnings> <source>1.8</source> <target>1.8</target> </configuration> <dependencies> <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-compiler-javac-errorprone</artifactId> <version>2.5</version> </dependency> <!-- override plexus-compiler-javac-errorprone's dependency on Error Prone with the latest version --> <dependency> <groupId>com.google.errorprone</groupId> <artifactId>error_prone_core</artifactId> <version>2.0.9</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>${maven.bundle.version}</version> <extensions>true</extensions> </plugin> <!-- Source jar --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <!-- Site (from https://github.com/asciidoctor/asciidoctor-maven-examples/blob/master/asciidoc-maven-site-example/pom.xml) --> <!-- + https://github.com/asciidoctor/asciidoctor-maven-plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-site-plugin</artifactId> <version>${maven.site.version}</version> <configuration> <generateReports>true</generateReports> <generateSitemap>true</generateSitemap> <relativizeDecorationLinks>false</relativizeDecorationLinks> <locales>en</locales> <inputEncoding>UTF-8</inputEncoding> <outputEncoding>UTF-8</outputEncoding> <siteDirectory>${project.basedir}</siteDirectory> <relativizeDecorationLinks>false</relativizeDecorationLinks> <asciidoc> <requires> <require>asciidoctor-diagram</require> </requires> <!-- optional site-wide AsciiDoc attributes --> <attributes> <source-highlighter>coderay</source-highlighter> <coderay-css>style</coderay-css> <icons>font</icons> <sectanchors>true</sectanchors> <idprefix/> <idseparator>-</idseparator> </attributes> </asciidoc> <!-- Exclude partial docs that are included elsewhere --> <moduleExcludes> <asciidoc>**/_*.adoc</asciidoc> </moduleExcludes> </configuration> <dependencies> <dependency> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>${asciidoctor.maven.plugin.version}</version> </dependency> <dependency> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctorj-diagram</artifactId> <version>${asciidoctorj.diagram.version}</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.codehaus.gmaven</groupId> <artifactId>groovy-maven-plugin</artifactId> <version>${maven.groovy.version}</version> <executions> <!-- Generate Readme.adoc if not present --> <execution> <id>generate-adoc</id> <phase>generate-resources</phase> <goals> <goal>execute</goal> </goals> <configuration> <!-- Generate module adoc documentation --> <source> io.fd.honeycomb.common.scripts.ReadmeGenerator.checkReadme(project, properties, log) </source> </configuration> </execution> <!-- Fix generated html --> <execution> <id>fix-generated-site</id> <phase>site</phase> <goals> <goal>execute</goal> </goals> <configuration> <!-- Site generates wrong link to Readme.html, trying to point to Readme.html at root --> <source> io.fd.honeycomb.common.scripts.ReadmeGenerator.fixSite(project, properties, log) </source> </configuration> </execution> <!-- copy generated schema pictures --> <execution> <id>copy-generated-pictures</id> <phase>site</phase> <goals> <goal>execute</goal> </goals> <configuration> <!-- Copies generated schema pictures from ascii-doctor folders to site folder--> <source> io.fd.honeycomb.common.scripts.AsciiDocImgForwarder.copyGeneratedImages(project, properties, log) </source> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>io.fd.honeycomb.doc</groupId> <artifactId>asciidoc-scripts</artifactId> <version>1.19.04-SNAPSHOT</version> </dependency> </dependencies> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <artifactId>maven-enforcer-plugin</artifactId> </plugin> <plugin> <artifactId>maven-source-plugin</artifactId> </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> </plugin> <plugin> <artifactId>maven-checkstyle-plugin</artifactId> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> </plugin> <plugin> <groupId>org.codehaus.gmaven</groupId> <artifactId>groovy-maven-plugin</artifactId> </plugin> </plugins> <!-- To support site push--> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-webdav-jackrabbit</artifactId> <version>2.9</version> </extension> </extensions> </build> <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-project-info-reports-plugin</artifactId> <version>${project.info.report.version}</version> <reportSets> <reportSet> <reports> <report>index</report> <report>summary</report> <report>modules</report> <report>cim</report> <report>dependencies</report> <report>distribution-management</report> <report>mailing-list</report> <report>issue-tracking</report> <report>license</report> <report>scm</report> </reports> </reportSet> </reportSets> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>${maven.javadoc.version}</version> <reportSets> <reportSet> <id>default</id> <reports> <report>javadoc-no-fork</report> </reports> </reportSet> </reportSets> <configuration> <additionalparam>-Xdoclint:none</additionalparam> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>${maven.resources.version}</version> </plugin> </plugins> </reporting> <distributionManagement> <repository> <id>fdio-release</id> <url>${nexusproxy}/repositories/fd.io.release/</url> </repository> <snapshotRepository> <id>fdio-snapshot</id> <url>${nexusproxy}/repositories/fd.io.snapshot/</url> </snapshotRepository> <site> <id>fdio-site</id> <url>dav:${docs.base.url}/${docs.hc.folder}/${project.version}</url> </site> </distributionManagement> <repositories> <!-- Using only ODL stable releases --> <repository> <releases> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>false</enabled> </snapshots> <id>opendaylight-mirror</id> <name>opendaylight-mirror</name> <url>${odl.nexusproxy}/repositories/public/</url> </repository> </repositories> </project>