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 #include <sys/errno.h> 28 #include <ipp/ipgpc/classifier.h> 29 30 /* Implementation file for behavior aggregate (BA) lookup table */ 31 32 /* 33 * ba_insert(bataid, filter_id, val, mask) 34 * 35 * inserts filter_id into element list of bataid->table->masked_values 36 * at position val& mask, mask is inserted into the mask list. 37 * filter_id shouldn't already exist in element list at 38 * bataid->table->masked_values[val], an error message is printed if this 39 * occurs. 40 * return DONTCARE_VALUE if mask == 0, NORMAL_VALUE otherwise 41 */ 42 int 43 ba_insert(ba_table_id_t *bataid, int filter_id, uint8_t val, uint8_t mask) 44 { 45 uint8_t mskd_val = val & mask; 46 ba_table_t *table = &bataid->table; 47 48 /* dontcares are not inserted */ 49 if (mask == 0) { 50 ++bataid->stats.num_dontcare; 51 return (DONTCARE_VALUE); 52 } 53 54 if (bataid->info.dontcareonly == B_TRUE) { 55 bataid->info.dontcareonly = B_FALSE; 56 } 57 58 if (ipgpc_list_insert(&table->masked_values[mskd_val].filter_list, 59 filter_id) == EEXIST) { 60 ipgpc0dbg(("ba_insert():filter_id %d EEXIST in ba_table", 61 filter_id)); 62 } else { 63 /* insert mask */ 64 (void) ipgpc_list_insert(&table->masks, mask); 65 /* update stats */ 66 ++table->masked_values[mskd_val].info; 67 ++bataid->stats.num_inserted; 68 } 69 return (NORMAL_VALUE); 70 } 71 72 /* 73 * ba_retrieve(bataid, value, fid_table) 74 * 75 * searches for all filters matching value in bataid->table 76 * search is performed by appling each mask in bataid->table->masks list 77 * to value and then looking value up in bataid->table->masked_values. 78 * Each filter id that is matched, is inserted into fid_table 79 * returns number of matched filters or (-1) if memory error 80 */ 81 int 82 ba_retrieve(ba_table_id_t *bataid, uint8_t value, ht_match_t *fid_table) 83 { 84 element_node_t *p; 85 element_node_t *filter_list; 86 int num_found = 0; 87 int ret; 88 int masked_value = 0; 89 ba_table_t *table = &bataid->table; 90 91 /* special case, if value == 0, no need to apply masks */ 92 if (value == 0) { 93 /* masked value will always be 0 for this case */ 94 filter_list = 95 table->masked_values[0].filter_list; 96 if ((num_found = ipgpc_mark_found(bataid->info.mask, 97 filter_list, fid_table)) == -1) { 98 return (-1); /* signifies a memory error */ 99 } 100 return (num_found); 101 } 102 103 /* apply each mask to the value and do the look up in the ba table */ 104 for (p = table->masks; p != NULL; p = p->next) { 105 masked_value = (uint8_t)(p->id) & value; 106 if (bataid->table.masked_values[masked_value].info == 0) { 107 /* masked_value has 0 filters associated with it */ 108 continue; 109 } 110 filter_list = 111 table->masked_values[masked_value].filter_list; 112 if ((ret = ipgpc_mark_found(bataid->info.mask, filter_list, 113 fid_table)) == -1) { 114 return (-1); /* signifies a memory error */ 115 } 116 num_found += ret; /* increment num_found */ 117 } 118 119 return (num_found); 120 } 121 122 /* 123 * ba_remove(bataid, filter_id, value, mask) 124 * 125 * removes filter_id from bataid->table->masked_values[mask & value] 126 * mask is removed from bataid->table->masks if refcnt == 0 for that list 127 */ 128 void 129 ba_remove(ba_table_id_t *bataid, int filter_id, uint8_t value, uint8_t mask) 130 { 131 uint8_t masked_value = value & mask; 132 ba_table_t *table = &bataid->table; 133 134 /* dontcares are not inserted */ 135 if (mask == 0) { 136 --bataid->stats.num_dontcare; 137 return; 138 } 139 140 if (ipgpc_list_remove(&table->masked_values[masked_value].filter_list, 141 filter_id) == B_TRUE) { 142 /* update stats */ 143 --table->masked_values[masked_value].info; 144 --bataid->stats.num_inserted; 145 /* 146 * check to see if removing this entry will result in 147 * don't cares only inserted in the table 148 */ 149 if (bataid->stats.num_inserted <= 0) { 150 bataid->info.dontcareonly = B_TRUE; 151 } 152 /* remove mask if refcnt == 0 */ 153 (void) ipgpc_list_remove(&table->masks, mask); 154 } 155 } 156