1c187222hselasky/*
2c187222hselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3c187222hselasky * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4c187222hselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5c187222hselasky * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
6c187222hselasky * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved.
7c187222hselasky * Copyright (c) 2009 HNR Consulting. All rights reserved.
8c187222hselasky * Copyright (c) 2009-2015 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
9c187222hselasky * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
10c187222hselasky *
11c187222hselasky * This software is available to you under a choice of one of two
12c187222hselasky * licenses.  You may choose to be licensed under the terms of the GNU
13c187222hselasky * General Public License (GPL) Version 2, available from the file
14c187222hselasky * COPYING in the main directory of this source tree, or the
15c187222hselasky * OpenIB.org BSD license below:
16c187222hselasky *
17c187222hselasky *     Redistribution and use in source and binary forms, with or
18c187222hselasky *     without modification, are permitted provided that the following
19c187222hselasky *     conditions are met:
20c187222hselasky *
21c187222hselasky *      - Redistributions of source code must retain the above
22c187222hselasky *        copyright notice, this list of conditions and the following
23c187222hselasky *        disclaimer.
24c187222hselasky *
25c187222hselasky *      - Redistributions in binary form must reproduce the above
26c187222hselasky *        copyright notice, this list of conditions and the following
27c187222hselasky *        disclaimer in the documentation and/or other materials
28c187222hselasky *        provided with the distribution.
29c187222hselasky *
30c187222hselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31c187222hselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32c187222hselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33c187222hselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
34c187222hselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
35c187222hselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
36c187222hselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37c187222hselasky * SOFTWARE.
38c187222hselasky *
39c187222hselasky */
40c187222hselasky
41c187222hselasky/*
42c187222hselasky * Abstract:
43c187222hselasky *    Implementation of osm_subn_t.
44c187222hselasky * This object represents an IBA subnet.
45c187222hselasky * This object is part of the opensm family of objects.
46c187222hselasky */
47c187222hselasky
48c187222hselasky#if HAVE_CONFIG_H
49c187222hselasky#  include <config.h>
50c187222hselasky#endif				/* HAVE_CONFIG_H */
51c187222hselasky
52c187222hselasky#include <string.h>
53c187222hselasky#include <stdio.h>
54c187222hselasky#include <stdarg.h>
55c187222hselasky#include <limits.h>
56c187222hselasky#include <errno.h>
57c187222hselasky#include <ctype.h>
58c187222hselasky#include <complib/cl_debug.h>
59c187222hselasky#include <complib/cl_log.h>
60c187222hselasky#include <opensm/osm_file_ids.h>
61c187222hselasky#define FILE_ID OSM_FILE_SUBNET_C
62c187222hselasky#include <opensm/osm_subnet.h>
63c187222hselasky#include <opensm/osm_opensm.h>
64c187222hselasky#include <opensm/osm_log.h>
65c187222hselasky#include <opensm/osm_madw.h>
66c187222hselasky#include <opensm/osm_port.h>
67c187222hselasky#include <opensm/osm_switch.h>
68c187222hselasky#include <opensm/osm_remote_sm.h>
69c187222hselasky#include <opensm/osm_partition.h>
70c187222hselasky#include <opensm/osm_node.h>
71c187222hselasky#include <opensm/osm_guid.h>
72c187222hselasky#include <opensm/osm_multicast.h>
73c187222hselasky#include <opensm/osm_inform.h>
74c187222hselasky#include <opensm/osm_console.h>
75c187222hselasky#include <opensm/osm_perfmgr.h>
76c187222hselasky#include <opensm/osm_congestion_control.h>
77c187222hselasky#include <opensm/osm_event_plugin.h>
78c187222hselasky#include <opensm/osm_qos_policy.h>
79c187222hselasky#include <opensm/osm_service.h>
80c187222hselasky#include <opensm/osm_db.h>
81c187222hselasky#include <opensm/osm_db_pack.h>
82c187222hselasky
83c187222hselaskystatic const char null_str[] = "(null)";
84c187222hselasky
85c187222hselasky#define OPT_OFFSET(opt) offsetof(osm_subn_opt_t, opt)
86c187222hselasky#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
87c187222hselasky
88c187222hselaskytypedef struct opt_rec {
89c187222hselasky	const char *name;
90c187222hselasky	unsigned long opt_offset;
91c187222hselasky	void (*parse_fn)(osm_subn_t *p_subn, char *p_key, char *p_val_str,
92c187222hselasky			 void *p_val1, void *p_val2,
93c187222hselasky			 void (*)(osm_subn_t *, void *));
94c187222hselasky	void (*setup_fn)(osm_subn_t *p_subn, void *p_val);
95c187222hselasky	int  can_update;
96c187222hselasky} opt_rec_t;
97c187222hselasky
98c187222hselaskystatic const char *module_name_str[] = {
99c187222hselasky	"main.c",
100c187222hselasky	"osm_console.c",
101c187222hselasky	"osm_console_io.c",
102c187222hselasky	"osm_db_files.c",
103c187222hselasky	"osm_db_pack.c",
104c187222hselasky	"osm_drop_mgr.c",
105c187222hselasky	"osm_dump.c",
106c187222hselasky	"osm_event_plugin.c",
107c187222hselasky	"osm_guid_info_rcv.c",
108c187222hselasky	"osm_guid_mgr.c",
109c187222hselasky	"osm_helper.c",
110c187222hselasky	"osm_inform.c",
111c187222hselasky	"osm_lid_mgr.c",
112c187222hselasky	"osm_lin_fwd_rcv.c",
113c187222hselasky	"osm_link_mgr.c",
114c187222hselasky	"osm_log.c",
115c187222hselasky	"osm_mad_pool.c",
116c187222hselasky	"osm_mcast_fwd_rcv.c",
117c187222hselasky	"osm_mcast_mgr.c",
118c187222hselasky	"osm_mcast_tbl.c",
119c187222hselasky	"osm_mcm_port.c",
120c187222hselasky	"osm_mesh.c",
121c187222hselasky	"osm_mlnx_ext_port_info_rcv.c",
122c187222hselasky	"osm_mtree.c",
123c187222hselasky	"osm_multicast.c",
124c187222hselasky	"osm_node.c",
125c187222hselasky	"osm_node_desc_rcv.c",
126c187222hselasky	"osm_node_info_rcv.c",
127c187222hselasky	"osm_opensm.c",
128c187222hselasky	"osm_perfmgr.c",
129c187222hselasky	"osm_perfmgr_db.c",
130c187222hselasky	"osm_pkey.c",
131c187222hselasky	"osm_pkey_mgr.c",
132c187222hselasky	"osm_pkey_rcv.c",
133c187222hselasky	"osm_port.c",
134c187222hselasky	"osm_port_info_rcv.c",
135c187222hselasky	"osm_prtn.c",
136c187222hselasky	"osm_prtn_config.c",
137c187222hselasky	"osm_qos.c",
138c187222hselasky	"osm_qos_parser_l.c",
139c187222hselasky	"osm_qos_parser_y.c",
140c187222hselasky	"osm_qos_policy.c",
141c187222hselasky	"osm_remote_sm.c",
142c187222hselasky	"osm_req.c",
143c187222hselasky	"osm_resp.c",
144c187222hselasky	"osm_router.c",
145c187222hselasky	"osm_sa.c",
146c187222hselasky	"osm_sa_class_port_info.c",
147c187222hselasky	"osm_sa_guidinfo_record.c",
148c187222hselasky	"osm_sa_informinfo.c",
149c187222hselasky	"osm_sa_lft_record.c",
150c187222hselasky	"osm_sa_link_record.c",
151c187222hselasky	"osm_sa_mad_ctrl.c",
152c187222hselasky	"osm_sa_mcmember_record.c",
153c187222hselasky	"osm_sa_mft_record.c",
154c187222hselasky	"osm_sa_multipath_record.c",
155c187222hselasky	"osm_sa_node_record.c",
156c187222hselasky	"osm_sa_path_record.c",
157c187222hselasky	"osm_sa_pkey_record.c",
158c187222hselasky	"osm_sa_portinfo_record.c",
159c187222hselasky	"osm_sa_service_record.c",
160c187222hselasky	"osm_sa_slvl_record.c",
161c187222hselasky	"osm_sa_sminfo_record.c",
162c187222hselasky	"osm_sa_sw_info_record.c",
163c187222hselasky	"osm_sa_vlarb_record.c",
164c187222hselasky	"osm_service.c",
165c187222hselasky	"osm_slvl_map_rcv.c",
166c187222hselasky	"osm_sm.c",
167c187222hselasky	"osm_sminfo_rcv.c",
168c187222hselasky	"osm_sm_mad_ctrl.c",
169c187222hselasky	"osm_sm_state_mgr.c",
170c187222hselasky	"osm_state_mgr.c",
171c187222hselasky	"osm_subnet.c",
172c187222hselasky	"osm_sw_info_rcv.c",
173c187222hselasky	"osm_switch.c",
174c187222hselasky	"osm_torus.c",
175c187222hselasky	"osm_trap_rcv.c",
176c187222hselasky	"osm_ucast_cache.c",
177c187222hselasky	"osm_ucast_dnup.c",
178c187222hselasky	"osm_ucast_file.c",
179c187222hselasky	"osm_ucast_ftree.c",
180c187222hselasky	"osm_ucast_lash.c",
181c187222hselasky	"osm_ucast_mgr.c",
182c187222hselasky	"osm_ucast_updn.c",
183c187222hselasky	"osm_vendor_ibumad.c",
184c187222hselasky	"osm_vl15intf.c",
185c187222hselasky	"osm_vl_arb_rcv.c",
186c187222hselasky	"st.c",
187c187222hselasky	"osm_ucast_dfsssp.c",
188c187222hselasky	"osm_congestion_control.c",
189c187222hselasky	/* Add new module names here ... */
190c187222hselasky	/* FILE_ID define in those modules must be identical to index here */
191c187222hselasky	/* last FILE_ID is currently 89 */
192c187222hselasky};
193c187222hselasky
194c187222hselasky#define MOD_NAME_STR_UNKNOWN_VAL (ARR_SIZE(module_name_str))
195c187222hselasky
196c187222hselaskystatic int find_module_name(const char *name, uint8_t *file_id)
197c187222hselasky{
198c187222hselasky	uint8_t i;
199c187222hselasky
200c187222hselasky	for (i = 0; i < MOD_NAME_STR_UNKNOWN_VAL; i++) {
201c187222hselasky		if (strcmp(name, module_name_str[i]) == 0) {
202c187222hselasky			if (file_id)
203c187222hselasky				*file_id = i;
204c187222hselasky			return 0;
205c187222hselasky		}
206c187222hselasky	}
207c187222hselasky	return 1;
208c187222hselasky}
209c187222hselasky
210c187222hselaskystatic void log_report(const char *fmt, ...)
211c187222hselasky{
212c187222hselasky	char buf[128];
213c187222hselasky	va_list args;
214c187222hselasky	va_start(args, fmt);
215c187222hselasky	vsnprintf(buf, sizeof(buf), fmt, args);
216c187222hselasky	va_end(args);
217c187222hselasky	printf("%s", buf);
218c187222hselasky	cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
219c187222hselasky}
220c187222hselasky
221c187222hselaskystatic void log_config_value(char *name, const char *fmt, ...)
222c187222hselasky{
223c187222hselasky	char buf[128];
224c187222hselasky	va_list args;
225c187222hselasky	unsigned n;
226c187222hselasky	va_start(args, fmt);
227c187222hselasky	n = snprintf(buf, sizeof(buf), " Loading Cached Option:%s = ", name);
228c187222hselasky	if (n > sizeof(buf))
229c187222hselasky		n = sizeof(buf);
230c187222hselasky	n += vsnprintf(buf + n, sizeof(buf) - n, fmt, args);
231c187222hselasky	if (n > sizeof(buf) - 2)
232c187222hselasky		n = sizeof(buf) - 2;
233c187222hselasky	snprintf(buf + n, sizeof(buf) - n, "\n");
234c187222hselasky	va_end(args);
235c187222hselasky	printf("%s", buf);
236c187222hselasky	cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
237c187222hselasky}
238c187222hselasky
239c187222hselaskystatic void opts_setup_log_flags(osm_subn_t *p_subn, void *p_val)
240c187222hselasky{
241c187222hselasky	p_subn->p_osm->log.level = *((uint8_t *) p_val);
242c187222hselasky}
243c187222hselasky
244c187222hselaskystatic void opts_setup_force_log_flush(osm_subn_t *p_subn, void *p_val)
245c187222hselasky{
246c187222hselasky	p_subn->p_osm->log.flush = *((boolean_t *) p_val);
247c187222hselasky}
248c187222hselasky
249c187222hselaskystatic void opts_setup_accum_log_file(osm_subn_t *p_subn, void *p_val)
250c187222hselasky{
251c187222hselasky	p_subn->p_osm->log.accum_log_file = *((boolean_t *) p_val);
252c187222hselasky}
253c187222hselasky
254c187222hselaskystatic void opts_setup_log_max_size(osm_subn_t *p_subn, void *p_val)
255c187222hselasky{
256c187222hselasky	uint32_t log_max_size = *((uint32_t *) p_val);
257c187222hselasky
258c187222hselasky	p_subn->p_osm->log.max_size = (unsigned long)log_max_size << 20; /* convert from MB to bytes */
259c187222hselasky}
260c187222hselasky
261c187222hselaskystatic void opts_setup_sminfo_polling_timeout(osm_subn_t *p_subn, void *p_val)
262c187222hselasky{
263c187222hselasky	osm_sm_t *p_sm = &p_subn->p_osm->sm;
264c187222hselasky	uint32_t sminfo_polling_timeout = *((uint32_t *) p_val);
265c187222hselasky
266c187222hselasky	cl_timer_stop(&p_sm->polling_timer);
267c187222hselasky	cl_timer_start(&p_sm->polling_timer, sminfo_polling_timeout);
268c187222hselasky}
269c187222hselasky
270c187222hselaskystatic void opts_setup_sm_priority(osm_subn_t *p_subn, void *p_val)
271c187222hselasky{
272c187222hselasky	osm_sm_t *p_sm = &p_subn->p_osm->sm;
273c187222hselasky	uint8_t sm_priority = *((uint8_t *) p_val);
274c187222hselasky
275c187222hselasky	osm_set_sm_priority(p_sm, sm_priority);
276c187222hselasky}
277c187222hselasky
278c187222hselaskystatic int opts_strtoul(uint32_t *val, IN char *p_val_str,
279c187222hselasky			IN char *p_key, uint32_t max_value)
280c187222hselasky{
281c187222hselasky	char *endptr;
282c187222hselasky	unsigned long int tmp_val;
283c187222hselasky
284c187222hselasky	errno = 0;
285c187222hselasky	tmp_val = strtoul(p_val_str, &endptr, 0);
286c187222hselasky	*val = tmp_val;
287c187222hselasky	if (*p_val_str == '\0' || *endptr != '\0') {
288c187222hselasky		log_report("-E- Parsing error in field %s, expected "
289c187222hselasky			   "numeric input received: %s\n", p_key, p_val_str);
290c187222hselasky		return -1;
291c187222hselasky	}
292c187222hselasky	if (tmp_val > max_value ||
293c187222hselasky	    ((tmp_val == ULONG_MAX) && errno == ERANGE)) {
294c187222hselasky		log_report("-E- Parsing error in field %s, value out of range\n", p_key);
295c187222hselasky		return -1;
296c187222hselasky	}
297c187222hselasky	return 0;
298c187222hselasky}
299c187222hselasky
300c187222hselaskystatic int opts_strtoull(uint64_t *val, IN char *p_val_str,
301c187222hselasky			 IN char *p_key, uint64_t max_value)
302c187222hselasky{
303c187222hselasky	char *endptr;
304c187222hselasky	unsigned long long int tmp_val;
305c187222hselasky
306c187222hselasky	errno = 0;
307c187222hselasky	tmp_val = strtoull(p_val_str, &endptr, 0);
308c187222hselasky	*val = tmp_val;
309c187222hselasky	if (*p_val_str == '\0' || *endptr != '\0') {
310c187222hselasky		log_report("-E- Parsing error in field %s, expected "
311c187222hselasky			   "numeric input received: %s\n", p_key, p_val_str);
312c187222hselasky		return -1;
313c187222hselasky	}
314c187222hselasky	if (tmp_val > max_value || (tmp_val == ULLONG_MAX && errno == ERANGE)) {
315c187222hselasky		log_report("-E- Parsing error in field %s, value out of range\n", p_key);
316c187222hselasky		return -1;
317c187222hselasky	}
318c187222hselasky	return 0;
319c187222hselasky}
320c187222hselasky
321c187222hselaskystatic void opts_parse_net64(IN osm_subn_t *p_subn, IN char *p_key,
322c187222hselasky			     IN char *p_val_str, void *p_v1, void *p_v2,
323c187222hselasky			     void (*pfn)(osm_subn_t *, void *))
324c187222hselasky{
325c187222hselasky	uint64_t *p_val1 = p_v1, *p_val2 = p_v2;
326c187222hselasky	uint64_t val;
327c187222hselasky
328c187222hselasky	if (opts_strtoull(&val, p_val_str, p_key, UINT64_MAX))
329c187222hselasky		return;
330c187222hselasky
331c187222hselasky	if (cl_hton64(val) != *p_val1) {
332c187222hselasky		log_config_value(p_key, "0x%016" PRIx64, val);
333c187222hselasky		if (pfn)
334c187222hselasky			pfn(p_subn, &val);
335c187222hselasky		*p_val1 = *p_val2 = cl_ntoh64(val);
336c187222hselasky	}
337c187222hselasky}
338c187222hselasky
339c187222hselaskystatic void opts_parse_uint32(IN osm_subn_t *p_subn, IN char *p_key,
340c187222hselasky			      IN char *p_val_str, void *p_v1, void *p_v2,
341c187222hselasky			      void (*pfn)(osm_subn_t *, void *))
342c187222hselasky{
343c187222hselasky	uint32_t *p_val1 = p_v1, *p_val2 = p_v2;
344c187222hselasky	uint32_t val;
345c187222hselasky
346c187222hselasky	if (opts_strtoul(&val, p_val_str, p_key, UINT32_MAX))
347c187222hselasky		return;
348c187222hselasky
349c187222hselasky	if (val != *p_val1) {
350c187222hselasky		log_config_value(p_key, "%u", val);
351c187222hselasky		if (pfn)
352c187222hselasky			pfn(p_subn, &val);
353c187222hselasky		*p_val1 = *p_val2 = val;
354c187222hselasky	}
355c187222hselasky}
356c187222hselasky
357c187222hselaskystatic void opts_parse_net32(IN osm_subn_t *p_subn, IN char *p_key,
358c187222hselasky			     IN char *p_val_str, void *p_v1, void *p_v2,
359c187222hselasky			     void (*pfn)(osm_subn_t *, void *))
360c187222hselasky{
361c187222hselasky	uint32_t *p_val1 = p_v1, *p_val2 = p_v2;
362c187222hselasky	uint32_t val;
363c187222hselasky
364c187222hselasky	if (opts_strtoul(&val, p_val_str, p_key, UINT32_MAX))
365c187222hselasky		return;
366c187222hselasky
367c187222hselasky	if (cl_hton32(val) != *p_val1) {
368c187222hselasky		log_config_value(p_key, "%u", val);
369c187222hselasky		if (pfn)
370c187222hselasky			pfn(p_subn, &val);
371c187222hselasky		*p_val1 = *p_val2 = cl_hton32(val);
372c187222hselasky	}
373c187222hselasky}
374c187222hselasky
375c187222hselaskystatic void opts_parse_int32(IN osm_subn_t *p_subn, IN char *p_key,
376c187222hselasky			     IN char *p_val_str, void *p_v1, void *p_v2,
377c187222hselasky			     void (*pfn)(osm_subn_t *, void *))
378c187222hselasky{
379c187222hselasky	int32_t *p_val1 = p_v1, *p_val2 = p_v2;
380c187222hselasky	int32_t val = strtol(p_val_str, NULL, 0);
381c187222hselasky
382c187222hselasky	if (val != *p_val1) {
383c187222hselasky		log_config_value(p_key, "%d", val);
384c187222hselasky		if (pfn)
385c187222hselasky			pfn(p_subn, &val);
386c187222hselasky		*p_val1 = *p_val2 = val;
387c187222hselasky	}
388c187222hselasky}
389c187222hselasky
390c187222hselaskystatic void opts_parse_uint16(IN osm_subn_t *p_subn, IN char *p_key,
391c187222hselasky			      IN char *p_val_str, void *p_v1, void *p_v2,
392c187222hselasky			      void (*pfn)(osm_subn_t *, void *))
393c187222hselasky{
394c187222hselasky	uint16_t *p_val1 = p_v1, *p_val2 = p_v2;
395c187222hselasky	uint32_t tmp_val;
396c187222hselasky
397c187222hselasky	if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT16_MAX))
398c187222hselasky		return;
399c187222hselasky
400c187222hselasky	uint16_t val = (uint16_t) tmp_val;
401c187222hselasky	if (val != *p_val1) {
402c187222hselasky		log_config_value(p_key, "%u", val);
403c187222hselasky		if (pfn)
404c187222hselasky			pfn(p_subn, &val);
405c187222hselasky		*p_val1 = *p_val2 = val;
406c187222hselasky	}
407c187222hselasky}
408c187222hselasky
409c187222hselaskystatic void opts_parse_net16(IN osm_subn_t *p_subn, IN char *p_key,
410c187222hselasky			     IN char *p_val_str, void *p_v1, void *p_v2,
411c187222hselasky			     void (*pfn)(osm_subn_t *, void *))
412c187222hselasky{
413c187222hselasky	uint16_t *p_val1 = p_v1, *p_val2 = p_v2;
414c187222hselasky	uint32_t tmp_val;
415c187222hselasky
416c187222hselasky	if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT16_MAX))
417c187222hselasky		return;
418c187222hselasky
419c187222hselasky	uint16_t val = (uint16_t) tmp_val;
420c187222hselasky	if (cl_hton16(val) != *p_val1) {
421c187222hselasky		log_config_value(p_key, "0x%04x", val);
422c187222hselasky		if (pfn)
423c187222hselasky			pfn(p_subn, &val);
424c187222hselasky		*p_val1 = *p_val2 = cl_hton16(val);
425c187222hselasky	}
426c187222hselasky}
427c187222hselasky
428c187222hselaskystatic void opts_parse_uint8(IN osm_subn_t *p_subn, IN char *p_key,
429c187222hselasky			     IN char *p_val_str, void *p_v1, void *p_v2,
430c187222hselasky			     void (*pfn)(osm_subn_t *, void *))
431c187222hselasky{
432c187222hselasky	uint8_t *p_val1 = p_v1, *p_val2 = p_v2;
433c187222hselasky	uint32_t tmp_val;
434c187222hselasky
435c187222hselasky	if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT8_MAX))
436c187222hselasky		return;
437c187222hselasky
438c187222hselasky	uint8_t val = (uint8_t) tmp_val;
439c187222hselasky	if (val != *p_val1) {
440c187222hselasky		log_config_value(p_key, "%u", val);
441c187222hselasky		if (pfn)
442c187222hselasky			pfn(p_subn, &val);
443c187222hselasky		*p_val1 = *p_val2 = val;
444c187222hselasky	}
445c187222hselasky}
446