X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Facl%2Fhash_lookup.c;h=07701b74babe25d8a4c76665a5f477f1193b5e36;hb=2c8e0023f91882e53f06eb99c901b97fe013f981;hp=c37aae44a98827fcdb3a5448f67723189fc5a073;hpb=6f40a8a4c5792c5c5e5c77366e98b1f10370d685;p=vpp.git diff --git a/src/plugins/acl/hash_lookup.c b/src/plugins/acl/hash_lookup.c index c37aae44a98..07701b74bab 100644 --- a/src/plugins/acl/hash_lookup.c +++ b/src/plugins/acl/hash_lookup.c @@ -280,7 +280,7 @@ assign_mask_type_index(acl_main_t *am, fa_5tuple_t *mask) if(~0 == mask_type_index) { pool_get_aligned (am->ace_mask_type_pool, mte, CLIB_CACHE_LINE_BYTES); mask_type_index = mte - am->ace_mask_type_pool; - clib_memcpy(&mte->mask, mask, sizeof(mte->mask)); + clib_memcpy_fast(&mte->mask, mask, sizeof(mte->mask)); mte->refcount = 0; /* @@ -315,7 +315,7 @@ release_mask_type_index(acl_main_t *am, u32 mask_type_index) DBG0("RELEAS MTE index %d new refcount %d", mask_type_index, mte->refcount); if (mte->refcount == 0) { /* we are not using this entry anymore */ - memset(mte, 0xae, sizeof(*mte)); + clib_memset(mte, 0xae, sizeof(*mte)); pool_put(am->ace_mask_type_pool, mte); } } @@ -447,7 +447,7 @@ remake_hash_applied_mask_info_vec (acl_main_t * am, if (minfo->mask_type_index == pae->mask_type_index) break; } - + vec_validate ((new_hash_applied_mask_info_vec), search); minfo = vec_elt_at_index ((new_hash_applied_mask_info_vec), search); if (search == new_pointer) @@ -541,6 +541,7 @@ add_colliding_rule (acl_main_t * am, cr.acl_position = pae->acl_position; cr.applied_entry_index = applied_entry_index; cr.rule = am->acls[pae->acl_index].rules[pae->ace_index]; + pae->collision_head_ae_index = head_index; vec_add1 (head_pae->colliding_rules, cr); if (ACL_HASH_LOOKUP_DEBUG > 0) acl_plugin_print_pae(acl_main.vlib_main, head_index, head_pae); @@ -554,7 +555,6 @@ activate_applied_ace_hash_entry(acl_main_t *am, { clib_bihash_kv_48_8_t kv; ASSERT(new_index != ~0); - applied_hash_ace_entry_t *pae = vec_elt_at_index((*applied_hash_aces), new_index); DBG("activate_applied_ace_hash_entry lc_index %d new_index %d", lc_index, new_index); fill_applied_hash_ace_kv(am, applied_hash_aces, lc_index, new_index, &kv); @@ -569,27 +569,17 @@ activate_applied_ace_hash_entry(acl_main_t *am, ASSERT(new_index != ~0); ASSERT(new_index < vec_len((*applied_hash_aces))); if (res == 0) { - /* There already exists an entry or more. Append at the end. */ u32 first_index = result_val->applied_entry_index; ASSERT(first_index != ~0); + ASSERT(first_index < vec_len((*applied_hash_aces))); + /* There already exists an entry or more. Append at the end. */ DBG("A key already exists, with applied entry index: %d", first_index); - applied_hash_ace_entry_t *first_pae = vec_elt_at_index((*applied_hash_aces), first_index); - u32 last_index = first_pae->tail_applied_entry_index; - ASSERT(last_index != ~0); - applied_hash_ace_entry_t *last_pae = vec_elt_at_index((*applied_hash_aces), last_index); - DBG("...advance to chained entry index: %d", last_index); - /* link ourselves in */ - last_pae->next_applied_entry_index = new_index; - pae->prev_applied_entry_index = last_index; - /* adjust the pointer to the new tail */ - first_pae->tail_applied_entry_index = new_index; add_colliding_rule(am, applied_hash_aces, first_index, new_index); return first_index; } else { /* It's the very first entry */ hashtable_add_del(am, &kv, 1); ASSERT(new_index != ~0); - pae->tail_applied_entry_index = new_index; add_colliding_rule(am, applied_hash_aces, new_index, new_index); return new_index; } @@ -600,13 +590,22 @@ static void * hash_acl_set_heap(acl_main_t *am) { if (0 == am->hash_lookup_mheap) { - am->hash_lookup_mheap = mheap_alloc_with_lock (0 /* use VM */ , + am->hash_lookup_mheap = mheap_alloc_with_lock (0 /* use VM */ , am->hash_lookup_mheap_size, 1 /* locked */); if (0 == am->hash_lookup_mheap) { - clib_error("ACL plugin failed to allocate lookup heap of %U bytes", + clib_error("ACL plugin failed to allocate lookup heap of %U bytes", format_memory_size, am->hash_lookup_mheap_size); } + /* + * DLMALLOC is being "helpful" in that it ignores the heap size parameter + * by default and tries to allocate the larger amount of memory. + * + * Pin the heap so this does not happen and if we run out of memory + * in this heap, we will bail out with "out of memory", rather than + * an obscure error sometime later. + */ + mspace_disable_expand(am->hash_lookup_mheap); } void *oldheap = clib_mem_set_heap(am->hash_lookup_mheap); return oldheap; @@ -617,17 +616,6 @@ acl_plugin_hash_acl_set_validate_heap(int on) { acl_main_t *am = &acl_main; clib_mem_set_heap(hash_acl_set_heap(am)); -#if USE_DLMALLOC == 0 - mheap_t *h = mheap_header (am->hash_lookup_mheap); - if (on) { - h->flags |= MHEAP_FLAG_VALIDATE; - h->flags &= ~MHEAP_FLAG_SMALL_OBJECT_CACHE; - mheap_validate(h); - } else { - h->flags &= ~MHEAP_FLAG_VALIDATE; - h->flags |= MHEAP_FLAG_SMALL_OBJECT_CACHE; - } -#endif } void @@ -635,14 +623,6 @@ acl_plugin_hash_acl_set_trace_heap(int on) { acl_main_t *am = &acl_main; clib_mem_set_heap(hash_acl_set_heap(am)); -#if USE_DLMALLOC == 0 - mheap_t *h = mheap_header (am->hash_lookup_mheap); - if (on) { - h->flags |= MHEAP_FLAG_TRACE; - } else { - h->flags &= ~MHEAP_FLAG_TRACE; - } -#endif } static void @@ -736,6 +716,14 @@ hash_acl_apply(acl_main_t *am, u32 lc_index, int acl_index, u32 acl_position) vec_validate(am->hash_applied_mask_info_vec_by_lc_index, lc_index); + + /* since we know (in case of no split) how much we expand, preallocate that space */ + if (vec_len(ha->rules) > 0) { + int old_vec_len = vec_len(*applied_hash_aces); + vec_validate((*applied_hash_aces), old_vec_len + vec_len(ha->rules) - 1); + _vec_len((*applied_hash_aces)) = old_vec_len; + } + /* add the rules from the ACL to the hash table for lookup and append to the vector*/ for(i=0; i < vec_len(ha->rules); i++) { /* @@ -754,9 +742,7 @@ hash_acl_apply(acl_main_t *am, u32 lc_index, int acl_index, u32 acl_position) pae->hitcount = 0; pae->hash_ace_info_index = i; /* we might link it in later */ - pae->next_applied_entry_index = ~0; - pae->prev_applied_entry_index = ~0; - pae->tail_applied_entry_index = ~0; + pae->collision_head_ae_index = ~0; pae->colliding_rules = NULL; pae->mask_type_index = ~0; assign_mask_type_index_to_pae(am, lc_index, is_ip6, pae); @@ -772,19 +758,21 @@ done: static u32 find_head_applied_ace_index(applied_hash_ace_entry_t **applied_hash_aces, u32 curr_index) { - /* - * find back the first entry. Inefficient so might need to be a bit cleverer - * if this proves to be a problem.. - */ - u32 an_index = curr_index; - ASSERT(an_index != ~0); - applied_hash_ace_entry_t *head_pae = vec_elt_at_index((*applied_hash_aces), an_index); - while(head_pae->prev_applied_entry_index != ~0) { - an_index = head_pae->prev_applied_entry_index; - ASSERT(an_index != ~0); - head_pae = vec_elt_at_index((*applied_hash_aces), an_index); - } - return an_index; + ASSERT(curr_index != ~0); + applied_hash_ace_entry_t *pae = vec_elt_at_index((*applied_hash_aces), curr_index); + ASSERT(pae); + ASSERT(pae->collision_head_ae_index != ~0); + return pae->collision_head_ae_index; +} + +static void +set_collision_head_ae_index(applied_hash_ace_entry_t **applied_hash_aces, collision_match_rule_t *colliding_rules, u32 new_index) +{ + collision_match_rule_t *cr; + vec_foreach(cr, colliding_rules) { + applied_hash_ace_entry_t *pae = vec_elt_at_index((*applied_hash_aces), cr->applied_entry_index); + pae->collision_head_ae_index = new_index; + } } static void @@ -807,35 +795,10 @@ move_applied_ace_hash_entry(acl_main_t *am, acl_plugin_print_pae(am->vlib_main, old_index, pae); } - if (new_pae->tail_applied_entry_index == old_index) { - /* fix-up the tail index if we are the tail and the start */ - new_pae->tail_applied_entry_index = new_index; - } - - if (pae->prev_applied_entry_index != ~0) { - applied_hash_ace_entry_t *prev_pae = vec_elt_at_index((*applied_hash_aces), pae->prev_applied_entry_index); - ASSERT(prev_pae->next_applied_entry_index == old_index); - prev_pae->next_applied_entry_index = new_index; - } else { + if (pae->collision_head_ae_index == old_index) { /* first entry - so the hash points to it, update */ add_del_hashtable_entry(am, lc_index, applied_hash_aces, new_index, 1); - ASSERT(pae->tail_applied_entry_index != ~0); - } - if (pae->next_applied_entry_index != ~0) { - applied_hash_ace_entry_t *next_pae = vec_elt_at_index((*applied_hash_aces), pae->next_applied_entry_index); - ASSERT(next_pae->prev_applied_entry_index == old_index); - next_pae->prev_applied_entry_index = new_index; - } else { - /* - * Moving the very last entry, so we need to update the tail pointer in the first one. - */ - u32 head_index = find_head_applied_ace_index(applied_hash_aces, old_index); - ASSERT(head_index != ~0); - applied_hash_ace_entry_t *head_pae = vec_elt_at_index((*applied_hash_aces), head_index); - - ASSERT(head_pae->tail_applied_entry_index == old_index); - head_pae->tail_applied_entry_index = new_index; } if (new_pae->colliding_rules) { /* update the information within the collision rule entry */ @@ -843,6 +806,7 @@ move_applied_ace_hash_entry(acl_main_t *am, collision_match_rule_t *cr = vec_elt_at_index (new_pae->colliding_rules, 0); ASSERT(cr->applied_entry_index == old_index); cr->applied_entry_index = new_index; + set_collision_head_ae_index(applied_hash_aces, new_pae->colliding_rules, new_index); } else { /* find the index in the collision rule entry on the head element */ u32 head_index = find_head_applied_ace_index(applied_hash_aces, new_index); @@ -862,9 +826,7 @@ move_applied_ace_hash_entry(acl_main_t *am, } } /* invalidate the old entry */ - pae->prev_applied_entry_index = ~0; - pae->next_applied_entry_index = ~0; - pae->tail_applied_entry_index = ~0; + pae->collision_head_ae_index = ~0; pae->colliding_rules = NULL; } @@ -881,40 +843,25 @@ deactivate_applied_ace_hash_entry(acl_main_t *am, acl_plugin_print_pae(am->vlib_main, old_index, pae); } - if (pae->prev_applied_entry_index != ~0) { - DBG("UNAPPLY = index %d has prev_applied_entry_index %d", old_index, pae->prev_applied_entry_index); - applied_hash_ace_entry_t *prev_pae = vec_elt_at_index((*applied_hash_aces), pae->prev_applied_entry_index); - ASSERT(prev_pae->next_applied_entry_index == old_index); - prev_pae->next_applied_entry_index = pae->next_applied_entry_index; + if (pae->collision_head_ae_index != old_index) { + DBG("UNAPPLY = index %d has collision head %d", old_index, pae->collision_head_ae_index); u32 head_index = find_head_applied_ace_index(applied_hash_aces, old_index); ASSERT(head_index != ~0); - applied_hash_ace_entry_t *head_pae = vec_elt_at_index((*applied_hash_aces), head_index); del_colliding_rule(applied_hash_aces, head_index, old_index); - if (pae->next_applied_entry_index == ~0) { - /* it was a last entry we removed, update the pointer on the first one */ - ASSERT(head_pae->tail_applied_entry_index == old_index); - head_pae->tail_applied_entry_index = pae->prev_applied_entry_index; - } else { - applied_hash_ace_entry_t *next_pae = vec_elt_at_index((*applied_hash_aces), pae->next_applied_entry_index); - next_pae->prev_applied_entry_index = pae->prev_applied_entry_index; - } } else { /* It was the first entry. We need either to reset the hash entry or delete it */ /* delete our entry from the collision vector first */ del_colliding_rule(applied_hash_aces, old_index, old_index); - if (pae->next_applied_entry_index != ~0) { - /* the next element becomes the new first one, so needs the tail pointer to be set */ - applied_hash_ace_entry_t *next_pae = vec_elt_at_index((*applied_hash_aces), pae->next_applied_entry_index); - ASSERT(pae->tail_applied_entry_index != ~0); - next_pae->tail_applied_entry_index = pae->tail_applied_entry_index; + if (vec_len(pae->colliding_rules) > 0) { + u32 next_pae_index = pae->colliding_rules[0].applied_entry_index; + applied_hash_ace_entry_t *next_pae = vec_elt_at_index((*applied_hash_aces), next_pae_index); /* Remove ourselves and transfer the ownership of the colliding rules vector */ next_pae->colliding_rules = pae->colliding_rules; - /* unlink from the next element */ - next_pae->prev_applied_entry_index = ~0; + set_collision_head_ae_index(applied_hash_aces, next_pae->colliding_rules, next_pae_index); add_del_hashtable_entry(am, lc_index, - applied_hash_aces, pae->next_applied_entry_index, 1); + applied_hash_aces, next_pae_index, 1); } else { /* no next entry, so just delete the entry in the hash table */ add_del_hashtable_entry(am, lc_index, @@ -925,9 +872,7 @@ deactivate_applied_ace_hash_entry(acl_main_t *am, release_mask_type_index(am, pae->mask_type_index); /* invalidate the old entry */ pae->mask_type_index = ~0; - pae->prev_applied_entry_index = ~0; - pae->next_applied_entry_index = ~0; - pae->tail_applied_entry_index = ~0; + pae->collision_head_ae_index = ~0; /* always has to be 0 */ pae->colliding_rules = NULL; } @@ -1057,7 +1002,7 @@ ip4_address_mask_from_width (ip4_address_t * a, u32 width) { int i, byte, bit, bitnum; ASSERT (width <= 32); - memset (a, 0, sizeof (a[0])); + clib_memset (a, 0, sizeof (a[0])); for (i = 0; i < width; i++) { bitnum = (7 - (i & 7)); @@ -1090,8 +1035,8 @@ make_port_mask(u16 *portmask, u16 port_first, u16 port_last) static void make_mask_and_match_from_rule(fa_5tuple_t *mask, acl_rule_t *r, hash_ace_info_t *hi) { - memset(mask, 0, sizeof(*mask)); - memset(&hi->match, 0, sizeof(hi->match)); + clib_memset(mask, 0, sizeof(*mask)); + clib_memset(&hi->match, 0, sizeof(hi->match)); hi->action = r->is_permit; /* we will need to be matching based on lc_index and mask_type_index when applied */ @@ -1107,7 +1052,7 @@ make_mask_and_match_from_rule(fa_5tuple_t *mask, acl_rule_t *r, hash_ace_info_t make_ip6_address_mask(&mask->ip6_addr[1], r->dst_prefixlen); hi->match.ip6_addr[1] = r->dst.ip6; } else { - memset(hi->match.l3_zero_pad, 0, sizeof(hi->match.l3_zero_pad)); + clib_memset(hi->match.l3_zero_pad, 0, sizeof(hi->match.l3_zero_pad)); make_ip4_address_mask(&mask->ip4_addr[0], r->src_prefixlen); hi->match.ip4_addr[0] = r->src.ip4; make_ip4_address_mask(&mask->ip4_addr[1], r->dst_prefixlen); @@ -1163,22 +1108,29 @@ void hash_acl_add(acl_main_t *am, int acl_index) void *oldheap = hash_acl_set_heap(am); DBG("HASH ACL add : %d", acl_index); int i; - acl_list_t *a = &am->acls[acl_index]; + acl_rule_t *acl_rules = am->acls[acl_index].rules; vec_validate(am->hash_acl_infos, acl_index); hash_acl_info_t *ha = vec_elt_at_index(am->hash_acl_infos, acl_index); - memset(ha, 0, sizeof(*ha)); + clib_memset(ha, 0, sizeof(*ha)); ha->hash_acl_exists = 1; /* walk the newly added ACL entries and ensure that for each of them there is a mask type, increment a reference count for that mask type */ - for(i=0; i < a->count; i++) { + + /* avoid small requests by preallocating the entire vector before running the additions */ + if (vec_len(acl_rules) > 0) { + vec_validate(ha->rules, vec_len(acl_rules)-1); + vec_reset_length(ha->rules); + } + + for(i=0; i < vec_len(acl_rules); i++) { hash_ace_info_t ace_info; fa_5tuple_t mask; - memset(&ace_info, 0, sizeof(ace_info)); + clib_memset(&ace_info, 0, sizeof(ace_info)); ace_info.acl_index = acl_index; ace_info.ace_index = i; - make_mask_and_match_from_rule(&mask, &a->rules[i], &ace_info); + make_mask_and_match_from_rule(&mask, &acl_rules[i], &ace_info); mask.pkt.flags_reserved = 0b000; ace_info.base_mask_type_index = assign_mask_type_index(am, &mask); /* assign the mask type index for matching itself */ @@ -1308,11 +1260,10 @@ static void acl_plugin_print_pae (vlib_main_t * vm, int j, applied_hash_ace_entry_t * pae) { vlib_cli_output (vm, - " %4d: acl %d rule %d action %d bitmask-ready rule %d mask type index: %d colliding_rules: %d next %d prev %d tail %d hitcount %lld acl_pos: %d", + " %4d: acl %d rule %d action %d bitmask-ready rule %d mask type index: %d colliding_rules: %d collision_head_ae_idx %d hitcount %lld acl_pos: %d", j, pae->acl_index, pae->ace_index, pae->action, - pae->hash_ace_info_index, pae->mask_type_index, vec_len(pae->colliding_rules), pae->next_applied_entry_index, - pae->prev_applied_entry_index, - pae->tail_applied_entry_index, pae->hitcount, pae->acl_position); + pae->hash_ace_info_index, pae->mask_type_index, vec_len(pae->colliding_rules), pae->collision_head_ae_index, + pae->hitcount, pae->acl_position); int jj; for(jj=0; jjcolliding_rules); jj++) acl_plugin_print_colliding_rule(vm, jj, vec_elt_at_index(pae->colliding_rules, jj)); @@ -1481,12 +1432,16 @@ split_partition(acl_main_t *am, u32 first_index, hash_acl_info_t *ha = vec_elt_at_index(am->hash_acl_infos, pae->acl_index); hash_ace_info_t *ace_info; u32 coll_mask_type_index = pae->mask_type_index; - memset(&the_min_tuple, 0, sizeof(the_min_tuple)); - memset(&the_max_tuple, 0, sizeof(the_max_tuple)); + clib_memset(&the_min_tuple, 0, sizeof(the_min_tuple)); + clib_memset(&the_max_tuple, 0, sizeof(the_max_tuple)); int i=0; + collision_match_rule_t *colliding_rules = pae->colliding_rules; u64 collisions = vec_len(pae->colliding_rules); for(i=0; ihash_acl_infos, pae->acl_index); DBG( "TM-collision: base_ace:%d (ace_mask:%d, first_collision_mask:%d)", pae->ace_index, pae->mask_type_index, coll_mask_type_index); @@ -1498,8 +1453,8 @@ split_partition(acl_main_t *am, u32 first_index, if(pae->mask_type_index != coll_mask_type_index) continue; /* Computing min_mask and max_mask for colliding rules */ if(i==0){ - clib_memcpy(min_tuple, mask, sizeof(fa_5tuple_t)); - clib_memcpy(max_tuple, mask, sizeof(fa_5tuple_t)); + clib_memcpy_fast(min_tuple, mask, sizeof(fa_5tuple_t)); + clib_memcpy_fast(max_tuple, mask, sizeof(fa_5tuple_t)); }else{ int j; for(j=0; j<2; j++){ @@ -1535,8 +1490,6 @@ split_partition(acl_main_t *am, u32 first_index, if(mask->pkt.as_u64 > max_tuple->pkt.as_u64) max_tuple->pkt.as_u64 = mask->pkt.as_u64; } - - pae = pae->next_applied_entry_index == ~0 ? 0 : vec_elt_at_index((*applied_hash_aces), pae->next_applied_entry_index); } /* Computing field with max difference between (min/max)_mask */ @@ -1663,15 +1616,19 @@ split_partition(acl_main_t *am, u32 first_index, u32 r_ace_index = first_index; int repopulate_count = 0; -// for(i=0; ihash_acl_infos, pop_pae->acl_index); DBG( "TM-Population-collision: base_ace:%d (ace_mask:%d, first_collision_mask:%d)", pop_pae->ace_index, pop_pae->mask_type_index, coll_mask_type_index); - if(pop_pae->mask_type_index != coll_mask_type_index) continue; - u32 next_index = pop_pae->next_applied_entry_index; + ASSERT(pop_pae->mask_type_index == coll_mask_type_index); ace_info = vec_elt_at_index(ha->rules, pop_pae->hash_ace_info_index); mte = vec_elt_at_index(am->ace_mask_type_pool, ace_info->base_mask_type_index); @@ -1693,11 +1650,10 @@ split_partition(acl_main_t *am, u32 first_index, activate_applied_ace_hash_entry(am, lc_index, applied_hash_aces, r_ace_index); - r_ace_index = next_index; } + vec_free(temp_colliding_rules); DBG( "TM-Populate new partition-END"); DBG( "TM-split_partition - END"); } -