+static void
+ip_share_adjacency(ip_lookup_main_t * lm, u32 adj_index)
+{
+ ip_adjacency_t * adj = ip_get_adjacency(lm, adj_index);
+ uword * p;
+ u32 old_ai;
+ uword signature = vnet_ip_adjacency_signature (adj);
+
+ p = hash_get (lm->adj_index_by_signature, signature);
+ /* Hash collision? */
+ if (p)
+ {
+ /* Save the adj index, p[0] will be toast after the unset! */
+ old_ai = p[0];
+ hash_unset (lm->adj_index_by_signature, signature);
+ hash_set (lm->adj_index_by_signature, signature, adj_index);
+ adj->next_adj_with_signature = old_ai;
+ }
+ else
+ {
+ adj->next_adj_with_signature = 0;
+ hash_set (lm->adj_index_by_signature, signature, adj_index);
+ }
+}
+
+static void
+ip_unshare_adjacency(ip_lookup_main_t * lm, u32 adj_index)
+{
+ ip_adjacency_t * adj = ip_get_adjacency(lm, adj_index);
+ uword signature;
+ uword * p;
+ u32 this_ai;
+ ip_adjacency_t * this_adj, * prev_adj = 0;
+
+ signature = vnet_ip_adjacency_signature (adj);
+ p = hash_get (lm->adj_index_by_signature, signature);
+ if (p == 0)
+ return;
+
+ this_ai = p[0];
+ /* At the top of the signature chain (likely)? */
+ if (this_ai == adj_index)
+ {
+ if (adj->next_adj_with_signature == 0)
+ {
+ hash_unset (lm->adj_index_by_signature, signature);
+ return;
+ }
+ else
+ {
+ this_adj = ip_get_adjacency (lm, adj->next_adj_with_signature);
+ hash_unset (lm->adj_index_by_signature, signature);
+ hash_set (lm->adj_index_by_signature, signature,
+ this_adj->heap_handle);
+ }
+ }
+ else /* walk signature chain */
+ {
+ this_adj = ip_get_adjacency (lm, this_ai);
+ while (this_adj != adj)
+ {
+ prev_adj = this_adj;
+ this_adj = ip_get_adjacency
+ (lm, this_adj->next_adj_with_signature);
+ /*
+ * This can happen when creating the first multipath adj of a set
+ * We end up looking at the miss adjacency (handle==0).
+ */
+ if (this_adj->heap_handle == 0)
+ return;
+ }
+ prev_adj->next_adj_with_signature = this_adj->next_adj_with_signature;
+ }
+}
+