1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek * @file
3*5d5fbe79SDavid van Moolenbroek * SNMP thread synchronization implementation.
4*5d5fbe79SDavid van Moolenbroek */
5*5d5fbe79SDavid van Moolenbroek
6*5d5fbe79SDavid van Moolenbroek /*
7*5d5fbe79SDavid van Moolenbroek * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8*5d5fbe79SDavid van Moolenbroek * All rights reserved.
9*5d5fbe79SDavid van Moolenbroek *
10*5d5fbe79SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without modification,
11*5d5fbe79SDavid van Moolenbroek * are permitted provided that the following conditions are met:
12*5d5fbe79SDavid van Moolenbroek *
13*5d5fbe79SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright notice,
14*5d5fbe79SDavid van Moolenbroek * this list of conditions and the following disclaimer.
15*5d5fbe79SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright notice,
16*5d5fbe79SDavid van Moolenbroek * this list of conditions and the following disclaimer in the documentation
17*5d5fbe79SDavid van Moolenbroek * and/or other materials provided with the distribution.
18*5d5fbe79SDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote products
19*5d5fbe79SDavid van Moolenbroek * derived from this software without specific prior written permission.
20*5d5fbe79SDavid van Moolenbroek *
21*5d5fbe79SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22*5d5fbe79SDavid van Moolenbroek * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23*5d5fbe79SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24*5d5fbe79SDavid van Moolenbroek * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25*5d5fbe79SDavid van Moolenbroek * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26*5d5fbe79SDavid van Moolenbroek * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*5d5fbe79SDavid van Moolenbroek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*5d5fbe79SDavid van Moolenbroek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29*5d5fbe79SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30*5d5fbe79SDavid van Moolenbroek * OF SUCH DAMAGE.
31*5d5fbe79SDavid van Moolenbroek *
32*5d5fbe79SDavid van Moolenbroek * Author: Dirk Ziegelmeier <dziegel@gmx.de>
33*5d5fbe79SDavid van Moolenbroek */
34*5d5fbe79SDavid van Moolenbroek
35*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/snmp_opts.h"
36*5d5fbe79SDavid van Moolenbroek
37*5d5fbe79SDavid van Moolenbroek #if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */
38*5d5fbe79SDavid van Moolenbroek
39*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/snmp_threadsync.h"
40*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/snmp_core.h"
41*5d5fbe79SDavid van Moolenbroek #include "lwip/sys.h"
42*5d5fbe79SDavid van Moolenbroek #include <string.h>
43*5d5fbe79SDavid van Moolenbroek
44*5d5fbe79SDavid van Moolenbroek static void
call_synced_function(struct threadsync_data * call_data,snmp_threadsync_called_fn fn)45*5d5fbe79SDavid van Moolenbroek call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn)
46*5d5fbe79SDavid van Moolenbroek {
47*5d5fbe79SDavid van Moolenbroek sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex);
48*5d5fbe79SDavid van Moolenbroek call_data->threadsync_node->instance->sync_fn(fn, call_data);
49*5d5fbe79SDavid van Moolenbroek sys_sem_wait(&call_data->threadsync_node->instance->sem);
50*5d5fbe79SDavid van Moolenbroek sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex);
51*5d5fbe79SDavid van Moolenbroek }
52*5d5fbe79SDavid van Moolenbroek
53*5d5fbe79SDavid van Moolenbroek static void
threadsync_get_value_synced(void * ctx)54*5d5fbe79SDavid van Moolenbroek threadsync_get_value_synced(void *ctx)
55*5d5fbe79SDavid van Moolenbroek {
56*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)ctx;
57*5d5fbe79SDavid van Moolenbroek
58*5d5fbe79SDavid van Moolenbroek call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value);
59*5d5fbe79SDavid van Moolenbroek
60*5d5fbe79SDavid van Moolenbroek sys_sem_signal(&call_data->threadsync_node->instance->sem);
61*5d5fbe79SDavid van Moolenbroek }
62*5d5fbe79SDavid van Moolenbroek
63*5d5fbe79SDavid van Moolenbroek static s16_t
threadsync_get_value(struct snmp_node_instance * instance,void * value)64*5d5fbe79SDavid van Moolenbroek threadsync_get_value(struct snmp_node_instance* instance, void* value)
65*5d5fbe79SDavid van Moolenbroek {
66*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
67*5d5fbe79SDavid van Moolenbroek
68*5d5fbe79SDavid van Moolenbroek call_data->arg1.value = value;
69*5d5fbe79SDavid van Moolenbroek call_synced_function(call_data, threadsync_get_value_synced);
70*5d5fbe79SDavid van Moolenbroek
71*5d5fbe79SDavid van Moolenbroek return call_data->retval.s16;
72*5d5fbe79SDavid van Moolenbroek }
73*5d5fbe79SDavid van Moolenbroek
74*5d5fbe79SDavid van Moolenbroek static void
threadsync_set_test_synced(void * ctx)75*5d5fbe79SDavid van Moolenbroek threadsync_set_test_synced(void *ctx)
76*5d5fbe79SDavid van Moolenbroek {
77*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)ctx;
78*5d5fbe79SDavid van Moolenbroek
79*5d5fbe79SDavid van Moolenbroek call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
80*5d5fbe79SDavid van Moolenbroek
81*5d5fbe79SDavid van Moolenbroek sys_sem_signal(&call_data->threadsync_node->instance->sem);
82*5d5fbe79SDavid van Moolenbroek }
83*5d5fbe79SDavid van Moolenbroek
84*5d5fbe79SDavid van Moolenbroek static snmp_err_t
threadsync_set_test(struct snmp_node_instance * instance,u16_t len,void * value)85*5d5fbe79SDavid van Moolenbroek threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
86*5d5fbe79SDavid van Moolenbroek {
87*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
88*5d5fbe79SDavid van Moolenbroek
89*5d5fbe79SDavid van Moolenbroek call_data->arg1.value = value;
90*5d5fbe79SDavid van Moolenbroek call_data->arg2.len = len;
91*5d5fbe79SDavid van Moolenbroek call_synced_function(call_data, threadsync_set_test_synced);
92*5d5fbe79SDavid van Moolenbroek
93*5d5fbe79SDavid van Moolenbroek return call_data->retval.err;
94*5d5fbe79SDavid van Moolenbroek }
95*5d5fbe79SDavid van Moolenbroek
96*5d5fbe79SDavid van Moolenbroek static void
threadsync_set_value_synced(void * ctx)97*5d5fbe79SDavid van Moolenbroek threadsync_set_value_synced(void *ctx)
98*5d5fbe79SDavid van Moolenbroek {
99*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)ctx;
100*5d5fbe79SDavid van Moolenbroek
101*5d5fbe79SDavid van Moolenbroek call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
102*5d5fbe79SDavid van Moolenbroek
103*5d5fbe79SDavid van Moolenbroek sys_sem_signal(&call_data->threadsync_node->instance->sem);
104*5d5fbe79SDavid van Moolenbroek }
105*5d5fbe79SDavid van Moolenbroek
106*5d5fbe79SDavid van Moolenbroek static snmp_err_t
threadsync_set_value(struct snmp_node_instance * instance,u16_t len,void * value)107*5d5fbe79SDavid van Moolenbroek threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
108*5d5fbe79SDavid van Moolenbroek {
109*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
110*5d5fbe79SDavid van Moolenbroek
111*5d5fbe79SDavid van Moolenbroek call_data->arg1.value = value;
112*5d5fbe79SDavid van Moolenbroek call_data->arg2.len = len;
113*5d5fbe79SDavid van Moolenbroek call_synced_function(call_data, threadsync_set_value_synced);
114*5d5fbe79SDavid van Moolenbroek
115*5d5fbe79SDavid van Moolenbroek return call_data->retval.err;
116*5d5fbe79SDavid van Moolenbroek }
117*5d5fbe79SDavid van Moolenbroek
118*5d5fbe79SDavid van Moolenbroek static void
threadsync_release_instance_synced(void * ctx)119*5d5fbe79SDavid van Moolenbroek threadsync_release_instance_synced(void* ctx)
120*5d5fbe79SDavid van Moolenbroek {
121*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)ctx;
122*5d5fbe79SDavid van Moolenbroek
123*5d5fbe79SDavid van Moolenbroek call_data->proxy_instance.release_instance(&call_data->proxy_instance);
124*5d5fbe79SDavid van Moolenbroek
125*5d5fbe79SDavid van Moolenbroek sys_sem_signal(&call_data->threadsync_node->instance->sem);
126*5d5fbe79SDavid van Moolenbroek }
127*5d5fbe79SDavid van Moolenbroek
128*5d5fbe79SDavid van Moolenbroek static void
threadsync_release_instance(struct snmp_node_instance * instance)129*5d5fbe79SDavid van Moolenbroek threadsync_release_instance(struct snmp_node_instance *instance)
130*5d5fbe79SDavid van Moolenbroek {
131*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
132*5d5fbe79SDavid van Moolenbroek
133*5d5fbe79SDavid van Moolenbroek if (call_data->proxy_instance.release_instance != NULL) {
134*5d5fbe79SDavid van Moolenbroek call_synced_function(call_data, threadsync_release_instance_synced);
135*5d5fbe79SDavid van Moolenbroek }
136*5d5fbe79SDavid van Moolenbroek }
137*5d5fbe79SDavid van Moolenbroek
138*5d5fbe79SDavid van Moolenbroek static void
get_instance_synced(void * ctx)139*5d5fbe79SDavid van Moolenbroek get_instance_synced(void* ctx)
140*5d5fbe79SDavid van Moolenbroek {
141*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)ctx;
142*5d5fbe79SDavid van Moolenbroek const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
143*5d5fbe79SDavid van Moolenbroek
144*5d5fbe79SDavid van Moolenbroek call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
145*5d5fbe79SDavid van Moolenbroek
146*5d5fbe79SDavid van Moolenbroek sys_sem_signal(&call_data->threadsync_node->instance->sem);
147*5d5fbe79SDavid van Moolenbroek }
148*5d5fbe79SDavid van Moolenbroek
149*5d5fbe79SDavid van Moolenbroek static void
get_next_instance_synced(void * ctx)150*5d5fbe79SDavid van Moolenbroek get_next_instance_synced(void* ctx)
151*5d5fbe79SDavid van Moolenbroek {
152*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = (struct threadsync_data*)ctx;
153*5d5fbe79SDavid van Moolenbroek const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
154*5d5fbe79SDavid van Moolenbroek
155*5d5fbe79SDavid van Moolenbroek call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
156*5d5fbe79SDavid van Moolenbroek
157*5d5fbe79SDavid van Moolenbroek sys_sem_signal(&call_data->threadsync_node->instance->sem);
158*5d5fbe79SDavid van Moolenbroek }
159*5d5fbe79SDavid van Moolenbroek
160*5d5fbe79SDavid van Moolenbroek static snmp_err_t
do_sync(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance,snmp_threadsync_called_fn fn)161*5d5fbe79SDavid van Moolenbroek do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn)
162*5d5fbe79SDavid van Moolenbroek {
163*5d5fbe79SDavid van Moolenbroek const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node;
164*5d5fbe79SDavid van Moolenbroek struct threadsync_data *call_data = &threadsync_node->instance->data;
165*5d5fbe79SDavid van Moolenbroek
166*5d5fbe79SDavid van Moolenbroek if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) {
167*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID"));
168*5d5fbe79SDavid van Moolenbroek return SNMP_ERR_NOSUCHINSTANCE;
169*5d5fbe79SDavid van Moolenbroek }
170*5d5fbe79SDavid van Moolenbroek
171*5d5fbe79SDavid van Moolenbroek memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance));
172*5d5fbe79SDavid van Moolenbroek
173*5d5fbe79SDavid van Moolenbroek instance->reference.ptr = call_data;
174*5d5fbe79SDavid van Moolenbroek snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len);
175*5d5fbe79SDavid van Moolenbroek
176*5d5fbe79SDavid van Moolenbroek call_data->proxy_instance.node = &threadsync_node->target->node;
177*5d5fbe79SDavid van Moolenbroek call_data->threadsync_node = threadsync_node;
178*5d5fbe79SDavid van Moolenbroek
179*5d5fbe79SDavid van Moolenbroek call_data->arg1.root_oid = root_oid;
180*5d5fbe79SDavid van Moolenbroek call_data->arg2.root_oid_len = root_oid_len;
181*5d5fbe79SDavid van Moolenbroek call_synced_function(call_data, fn);
182*5d5fbe79SDavid van Moolenbroek
183*5d5fbe79SDavid van Moolenbroek if (call_data->retval.err == SNMP_ERR_NOERROR) {
184*5d5fbe79SDavid van Moolenbroek instance->access = call_data->proxy_instance.access;
185*5d5fbe79SDavid van Moolenbroek instance->asn1_type = call_data->proxy_instance.asn1_type;
186*5d5fbe79SDavid van Moolenbroek instance->release_instance = threadsync_release_instance;
187*5d5fbe79SDavid van Moolenbroek instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL;
188*5d5fbe79SDavid van Moolenbroek instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL;
189*5d5fbe79SDavid van Moolenbroek instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL;
190*5d5fbe79SDavid van Moolenbroek snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len);
191*5d5fbe79SDavid van Moolenbroek }
192*5d5fbe79SDavid van Moolenbroek
193*5d5fbe79SDavid van Moolenbroek return call_data->retval.err;
194*5d5fbe79SDavid van Moolenbroek }
195*5d5fbe79SDavid van Moolenbroek
196*5d5fbe79SDavid van Moolenbroek snmp_err_t
snmp_threadsync_get_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)197*5d5fbe79SDavid van Moolenbroek snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
198*5d5fbe79SDavid van Moolenbroek {
199*5d5fbe79SDavid van Moolenbroek return do_sync(root_oid, root_oid_len, instance, get_instance_synced);
200*5d5fbe79SDavid van Moolenbroek }
201*5d5fbe79SDavid van Moolenbroek
202*5d5fbe79SDavid van Moolenbroek snmp_err_t
snmp_threadsync_get_next_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)203*5d5fbe79SDavid van Moolenbroek snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
204*5d5fbe79SDavid van Moolenbroek {
205*5d5fbe79SDavid van Moolenbroek return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced);
206*5d5fbe79SDavid van Moolenbroek }
207*5d5fbe79SDavid van Moolenbroek
208*5d5fbe79SDavid van Moolenbroek /** Initializes thread synchronization instance */
snmp_threadsync_init(struct snmp_threadsync_instance * instance,snmp_threadsync_synchronizer_fn sync_fn)209*5d5fbe79SDavid van Moolenbroek void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn)
210*5d5fbe79SDavid van Moolenbroek {
211*5d5fbe79SDavid van Moolenbroek err_t err = sys_mutex_new(&instance->sem_usage_mutex);
212*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
213*5d5fbe79SDavid van Moolenbroek err = sys_sem_new(&instance->sem, 0);
214*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
215*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
216*5d5fbe79SDavid van Moolenbroek instance->sync_fn = sync_fn;
217*5d5fbe79SDavid van Moolenbroek }
218*5d5fbe79SDavid van Moolenbroek
219*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_SNMP */
220