1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/errno.h> 30 #include <ipp/ipgpc/classifier.h> 31 32 /* Implementation file for behavior aggregate (BA) lookup table */ 33 34 /* 35 * ba_insert(bataid, filter_id, val, mask) 36 * 37 * inserts filter_id into element list of bataid->table->masked_values 38 * at position val& mask, mask is inserted into the mask list. 39 * filter_id shouldn't already exist in element list at 40 * bataid->table->masked_values[val], an error message is printed if this 41 * occurs. 42 * return DONTCARE_VALUE if mask == 0, NORMAL_VALUE otherwise 43 */ 44 int 45 ba_insert(ba_table_id_t *bataid, int filter_id, uint8_t val, uint8_t mask) 46 { 47 uint8_t mskd_val = val & mask; 48 ba_table_t *table = &bataid->table; 49 50 /* dontcares are not inserted */ 51 if (mask == 0) { 52 ++bataid->stats.num_dontcare; 53 return (DONTCARE_VALUE); 54 } 55 56 if (bataid->info.dontcareonly == B_TRUE) { 57 bataid->info.dontcareonly = B_FALSE; 58 } 59 60 if (ipgpc_list_insert(&table->masked_values[mskd_val].filter_list, 61 filter_id) == EEXIST) { 62 ipgpc0dbg(("ba_insert():filter_id %d EEXIST in ba_table", 63 filter_id)); 64 } else { 65 /* insert mask */ 66 (void) ipgpc_list_insert(&table->masks, mask); 67 /* update stats */ 68 ++table->masked_values[mskd_val].info; 69 ++bataid->stats.num_inserted; 70 } 71 return (NORMAL_VALUE); 72 } 73 74 /* 75 * ba_retrieve(bataid, value, fid_table) 76 * 77 * searches for all filters matching value in bataid->table 78 * search is performed by appling each mask in bataid->table->masks list 79 * to value and then looking value up in bataid->table->masked_values. 80 * Each filter id that is matched, is inserted into fid_table 81 * returns number of matched filters or (-1) if memory error 82 */ 83 int 84 ba_retrieve(ba_table_id_t *bataid, uint8_t value, ht_match_t *fid_table) 85 { 86 element_node_t *p; 87 element_node_t *filter_list; 88 int num_found = 0; 89 int ret; 90 int masked_value = 0; 91 ba_table_t *table = &bataid->table; 92 93 /* special case, if value == 0, no need to apply masks */ 94 if (value == 0) { 95 /* masked value will always be 0 for this case */ 96 filter_list = 97 table->masked_values[0].filter_list; 98 if ((num_found = ipgpc_mark_found(bataid->info.mask, 99 filter_list, fid_table)) == -1) { 100 return (-1); /* signifies a memory error */ 101 } 102 return (num_found); 103 } 104 105 /* apply each mask to the value and do the look up in the ba table */ 106 for (p = table->masks; p != NULL; p = p->next) { 107 masked_value = (uint8_t)(p->id) & value; 108 if (bataid->table.masked_values[masked_value].info == 0) { 109 /* masked_value has 0 filters associated with it */ 110 continue; 111 } 112 filter_list = 113 table->masked_values[masked_value].filter_list; 114 if ((ret = ipgpc_mark_found(bataid->info.mask, filter_list, 115 fid_table)) == -1) { 116 return (-1); /* signifies a memory error */ 117 } 118 num_found += ret; /* increment num_found */ 119 } 120 121 return (num_found); 122 } 123 124 /* 125 * ba_remove(bataid, filter_id, value, mask) 126 * 127 * removes filter_id from bataid->table->masked_values[mask & value] 128 * mask is removed from bataid->table->masks if refcnt == 0 for that list 129 */ 130 void 131 ba_remove(ba_table_id_t *bataid, int filter_id, uint8_t value, uint8_t mask) 132 { 133 uint8_t masked_value = value & mask; 134 ba_table_t *table = &bataid->table; 135 136 /* dontcares are not inserted */ 137 if (mask == 0) { 138 --bataid->stats.num_dontcare; 139 return; 140 } 141 142 if (ipgpc_list_remove(&table->masked_values[masked_value].filter_list, 143 filter_id) == B_TRUE) { 144 /* update stats */ 145 --table->masked_values[masked_value].info; 146 --bataid->stats.num_inserted; 147 /* 148 * check to see if removing this entry will result in 149 * don't cares only inserted in the table 150 */ 151 if (bataid->stats.num_inserted <= 0) { 152 bataid->info.dontcareonly = B_TRUE; 153 } 154 /* remove mask if refcnt == 0 */ 155 (void) ipgpc_list_remove(&table->masks, mask); 156 } 157 } 158