2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Implementation of osm_pkt_randomizer_t.
44 #endif /* HAVE_CONFIG_H */
46 #include <vendor/osm_pkt_randomizer.h>
55 /**********************************************************************
56 * Return TRUE if the path is in a fault path, and FALSE otherwise.
57 * By in a fault path the meaning is that there is a path in the fault
58 * paths that the given path includes it.
59 * E.g: if there is a fault path: 0,1,4
60 * For the given path: 0,1,4,7 the return value will be TRUE, also for
61 * the given path: 0,1,4 the return value will be TRUE, but for
62 * the given paths: 0,1 or 0,3,1,4 - the return value will be FALSE.
63 **********************************************************************/
65 __osm_pkt_randomizer_is_path_in_fault_paths(IN osm_log_t * p_log,
66 IN osm_dr_path_t * p_dr_path,
67 IN osm_pkt_randomizer_t *
70 boolean_t res = FALSE, found_path;
71 osm_dr_path_t *p_found_dr_path;
76 for (ind1 = 0; ind1 < p_pkt_rand->num_paths_initialized; ind1++) {
78 p_found_dr_path = &(p_pkt_rand->fault_dr_paths[ind1]);
79 /* if the hop count of the found path is greater than the
80 hop count of the input path - then it is not part of it.
81 Check the next path. */
82 if (p_found_dr_path->hop_count > p_dr_path->hop_count)
85 /* go over all the ports in the found path and see if they match
86 the ports in the input path */
87 for (ind2 = 0; ind2 <= p_found_dr_path->hop_count; ind2++)
88 if (p_found_dr_path->path[ind2] !=
89 p_dr_path->path[ind2])
92 /* If found_path is TRUE then there is a full match of the path */
93 if (found_path == TRUE) {
94 OSM_LOG(p_log, OSM_LOG_VERBOSE,
95 "Given path is in a fault path\n");
105 /**********************************************************************
106 * For a given dr_path - return TRUE if the path should be dropped,
107 * return FALSE otherwise.
108 * The check uses random criteria in order to determine whether or not
109 * the path should be dropped.
110 * First - if not all paths are initialized, it randomally chooses if
111 * to use this path as a fault path or not.
112 * Second - if the path is in the fault paths (meaning - it is equal
113 * to or includes one of the fault paths) - then it randomally chooses
114 * if to drop it or not.
115 **********************************************************************/
117 __osm_pkt_randomizer_process_path(IN osm_log_t * p_log,
118 IN osm_pkt_randomizer_t * p_pkt_rand,
119 IN osm_dr_path_t * p_dr_path)
121 boolean_t res = FALSE;
122 static boolean_t rand_value_init = FALSE;
123 static int rand_value;
124 boolean_t in_fault_paths;
129 OSM_LOG_ENTER(p_log);
131 if (rand_value_init == FALSE) {
140 /* initiate the rand_value according to timeofday */
141 rand_value_init = TRUE;
145 seed = st.wMilliseconds;
147 gettimeofday(&tv, &tz);
154 /* If the hop_count is 1 - then this is a mad down to our local port - don't drop it */
155 if (p_dr_path->hop_count <= 1)
160 sprintf(buf, "Path: ");
161 /* update the dr_path into the buf */
162 for (i = 0; i <= p_dr_path->hop_count; i++) {
163 sprintf(line, "[%X]", p_dr_path->path[i]);
167 /* Check if the path given is in one of the fault paths */
169 __osm_pkt_randomizer_is_path_in_fault_paths(p_log, p_dr_path,
172 /* Check if all paths are initialized */
173 if (p_pkt_rand->num_paths_initialized <
174 p_pkt_rand->osm_pkt_num_unstable_links) {
175 /* Not all packets are initialized. */
176 if (in_fault_paths == FALSE) {
177 /* the path is not in the false paths. Check using the rand value
178 if to update it there or not. */
180 (p_pkt_rand->osm_pkt_unstable_link_rate) == 0) {
181 OSM_LOG(p_log, OSM_LOG_VERBOSE,
182 "%s added to the fault_dr_paths list\n"
183 "\t\t\t rand_value:%u, unstable_link_rate:%u \n",
185 p_pkt_rand->osm_pkt_unstable_link_rate);
187 /* update the path in the fault paths */
190 fault_dr_paths[p_pkt_rand->
191 num_paths_initialized]),
192 p_dr_path, sizeof(osm_dr_path_t));
193 p_pkt_rand->num_paths_initialized++;
194 in_fault_paths = TRUE;
199 if (in_fault_paths == FALSE) {
200 /* If in_fault_paths is FALSE - just ignore the path */
201 OSM_LOG(p_log, OSM_LOG_VERBOSE, "%s not in fault paths\n", buf);
205 /* The path is in the fault paths. Need to choose (randomally if to drop it
209 if (rand_value % (p_pkt_rand->osm_pkt_drop_rate) == 0) {
210 /* drop the current packet */
212 OSM_LOG(p_log, OSM_LOG_VERBOSE, "Dropping path:%s\n", buf);
220 /**********************************************************************
221 **********************************************************************/
223 osm_pkt_randomizer_mad_drop(IN osm_log_t * p_log,
224 IN osm_pkt_randomizer_t * p_pkt_randomizer,
225 IN const ib_mad_t * p_mad)
227 const ib_smp_t *p_smp;
228 boolean_t res = FALSE;
229 osm_dr_path_t dr_path;
231 OSM_LOG_ENTER(p_log);
233 p_smp = (ib_smp_t *) p_mad;
235 if (p_smp->mgmt_class != IB_MCLASS_SUBN_DIR)
236 /* This is a lid route mad. Don't drop it */
239 osm_dr_path_init(&dr_path, 0, /* The h_bind is not really important for us to save */
240 p_smp->hop_count, p_smp->initial_path);
242 if (__osm_pkt_randomizer_process_path
243 (p_log, p_pkt_randomizer, &dr_path)) {
244 /* the mad should be dropped o */
245 OSM_LOG(p_log, OSM_LOG_VERBOSE,
246 "mad TID: 0x%" PRIx64 " is being dropped\n",
247 cl_ntoh64(p_smp->trans_id));
256 /**********************************************************************
257 **********************************************************************/
259 osm_pkt_randomizer_init(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer,
260 IN osm_log_t * p_log)
263 ib_api_status_t res = IB_SUCCESS;
265 OSM_LOG_ENTER(p_log);
267 *pp_pkt_randomizer = malloc(sizeof(osm_pkt_randomizer_t));
268 if (*pp_pkt_randomizer == NULL) {
269 res = IB_INSUFFICIENT_MEMORY;
272 memset(*pp_pkt_randomizer, 0, sizeof(osm_pkt_randomizer_t));
273 (*pp_pkt_randomizer)->num_paths_initialized = 0;
275 tmp = atol(getenv("OSM_PKT_DROP_RATE"));
276 (*pp_pkt_randomizer)->osm_pkt_drop_rate = tmp;
278 if (getenv("OSM_PKT_NUM_UNSTABLE_LINKS") != NULL
279 && (tmp = atol(getenv("OSM_PKT_NUM_UNSTABLE_LINKS"))) > 0)
280 (*pp_pkt_randomizer)->osm_pkt_num_unstable_links = tmp;
282 (*pp_pkt_randomizer)->osm_pkt_num_unstable_links = 1;
284 if (getenv("OSM_PKT_UNSTABLE_LINK_RATE") != NULL
285 && (tmp = atol(getenv("OSM_PKT_UNSTABLE_LINK_RATE"))) > 0)
286 (*pp_pkt_randomizer)->osm_pkt_unstable_link_rate = tmp;
288 (*pp_pkt_randomizer)->osm_pkt_unstable_link_rate = 20;
290 OSM_LOG(p_log, OSM_LOG_VERBOSE, "Using OSM_PKT_DROP_RATE=%u \n"
291 "\t\t\t\t OSM_PKT_NUM_UNSTABLE_LINKS=%u \n"
292 "\t\t\t\t OSM_PKT_UNSTABLE_LINK_RATE=%u \n",
293 (*pp_pkt_randomizer)->osm_pkt_drop_rate,
294 (*pp_pkt_randomizer)->osm_pkt_num_unstable_links,
295 (*pp_pkt_randomizer)->osm_pkt_unstable_link_rate);
297 /* allocate the fault_dr_paths variable */
298 /* It is the number of the paths that will be saved as fault = osm_pkt_num_unstable_links */
299 (*pp_pkt_randomizer)->fault_dr_paths = malloc(sizeof(osm_dr_path_t) *
300 (*pp_pkt_randomizer)->
301 osm_pkt_num_unstable_links);
302 if ((*pp_pkt_randomizer)->fault_dr_paths == NULL) {
303 res = IB_INSUFFICIENT_MEMORY;
307 memset((*pp_pkt_randomizer)->fault_dr_paths, 0,
308 sizeof(osm_dr_path_t) *
309 (*pp_pkt_randomizer)->osm_pkt_num_unstable_links);
316 /**********************************************************************
317 **********************************************************************/
319 osm_pkt_randomizer_destroy(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer,
320 IN osm_log_t * p_log)
322 OSM_LOG_ENTER(p_log);
324 if (*pp_pkt_randomizer != NULL) {
325 free((*pp_pkt_randomizer)->fault_dr_paths);
326 free(*pp_pkt_randomizer);