udp: Make the SNMP code asynchronous
Do not block the application when doing a SNMP request. Work with the results coming back from the callback. Right now a link can only be taken down and up.
This commit is contained in:
parent
4da421da6f
commit
eab20964b2
|
@ -141,7 +141,7 @@ void update_con_state(struct mtp_link_set *link, int rc, struct sccp_parse_resul
|
|||
unsigned int sls_for_src_ref(struct sccp_source_reference *ref);
|
||||
|
||||
/* udp init */
|
||||
int link_global_init(struct mtp_udp_data *data, int src_port);
|
||||
int link_global_init(struct mtp_udp_data *data, char *dest_ip, int src_port);
|
||||
int link_udp_init(struct mtp_udp_link *data, const char *dest_ip, int port);
|
||||
int link_init(struct bsc_data *bsc);
|
||||
int link_shutdown_all(struct mtp_link_set *);
|
||||
|
|
|
@ -26,6 +26,27 @@
|
|||
|
||||
struct snmp_mtp_session {
|
||||
netsnmp_session session, *ss;
|
||||
void *data;
|
||||
|
||||
/*
|
||||
* The callbacks will be called multiple times. Even if
|
||||
* we only toggle one object. Remember which request we
|
||||
* are handling here and then we will claim success on the
|
||||
* first of a series of PDUs. This is the easies to manage
|
||||
* and if a link fails to come up the SLTM will catch it.
|
||||
*/
|
||||
int last_up_req;
|
||||
int last_do_req;
|
||||
};
|
||||
|
||||
enum {
|
||||
SNMP_LINK_UP,
|
||||
SNMP_LINK_DOWN,
|
||||
};
|
||||
|
||||
enum {
|
||||
SNMP_STATUS_OK,
|
||||
SNMP_STATUS_TIMEOUT,
|
||||
};
|
||||
|
||||
struct snmp_mtp_session *snmp_mtp_session_create(char *host);
|
||||
|
@ -33,4 +54,7 @@ void snmp_mtp_deactivate(struct snmp_mtp_session *, int link_id);
|
|||
void snmp_mtp_activate(struct snmp_mtp_session *, int link_id);
|
||||
void snmp_mtp_poll();
|
||||
|
||||
/* to be implemented by the handler */
|
||||
void snmp_mtp_callback(struct snmp_mtp_session *, int area, int res, int link_id);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -157,7 +157,6 @@ static void do_start(void *_data)
|
|||
struct mtp_udp_link *link = (struct mtp_udp_link *) _data;
|
||||
|
||||
snmp_mtp_activate(link->data->session, link->link_index);
|
||||
mtp_link_up(&link->base);
|
||||
}
|
||||
|
||||
static int udp_link_reset(struct mtp_link *link)
|
||||
|
@ -166,16 +165,7 @@ static int udp_link_reset(struct mtp_link *link)
|
|||
|
||||
ulnk = (struct mtp_udp_link *) link;
|
||||
|
||||
LOGP(DINP, LOGL_NOTICE, "Will restart SLTM transmission in %d seconds.\n",
|
||||
ulnk->reset_timeout);
|
||||
|
||||
snmp_mtp_deactivate(ulnk->data->session, ulnk->link_index);
|
||||
mtp_link_down(link);
|
||||
|
||||
/* restart the link in 90 seconds... to force a timeout on the BSC */
|
||||
link->link_activate.cb = do_start;
|
||||
link->link_activate.data = link;
|
||||
bsc_schedule_timer(&link->link_activate, ulnk->reset_timeout, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -239,12 +229,18 @@ static void snmp_poll(void *_data)
|
|||
bsc_schedule_timer(&data->snmp_poll, 0, 5000);
|
||||
}
|
||||
|
||||
int link_global_init(struct mtp_udp_data *data, int src_port)
|
||||
int link_global_init(struct mtp_udp_data *data, char *udp_ip, int src_port)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int fd;
|
||||
int on;
|
||||
|
||||
/* setup SNMP first, it is blocking */
|
||||
data->session = snmp_mtp_session_create(udp_ip);
|
||||
if (!data->session)
|
||||
return -1;
|
||||
data->session->data = data;
|
||||
|
||||
INIT_LLIST_HEAD(&data->links);
|
||||
write_queue_init(&data->write_queue, 100);
|
||||
|
||||
|
@ -287,3 +283,45 @@ int link_global_init(struct mtp_udp_data *data, int src_port)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void snmp_mtp_callback(struct snmp_mtp_session *session,
|
||||
int area, int res, int link_id)
|
||||
{
|
||||
struct mtp_udp_data *data;
|
||||
struct mtp_udp_link *ulink;
|
||||
struct mtp_link *link;
|
||||
|
||||
data = session->data;
|
||||
ulink = find_link(data, link_id);
|
||||
if (!ulink)
|
||||
return LOGP(DINP, LOGL_ERROR, "Failed to find link %d\n", link_id);
|
||||
|
||||
link = &ulink->base;
|
||||
|
||||
if (res == SNMP_STATUS_TIMEOUT) {
|
||||
LOGP(DINP, LOGL_ERROR, "Failed to restart link: %d\n", link_id);
|
||||
udp_link_reset(link);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (area) {
|
||||
case SNMP_LINK_UP:
|
||||
mtp_link_up(link);
|
||||
break;
|
||||
case SNMP_LINK_DOWN:
|
||||
mtp_link_down(link);
|
||||
|
||||
/*
|
||||
* restart the link in 90 seconds...
|
||||
* to force a timeout on the BSC
|
||||
*/
|
||||
link->link_activate.cb = do_start;
|
||||
link->link_activate.data = link;
|
||||
bsc_schedule_timer(&link->link_activate, ulink->reset_timeout, 0);
|
||||
LOGP(DINP, LOGL_NOTICE,
|
||||
"Will restart SLTM transmission in %d seconds.\n", ulink->reset_timeout);
|
||||
break;
|
||||
default:
|
||||
LOGP(DINP, LOGL_ERROR, "Unknown event %d\n", area);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,12 +126,7 @@ int link_init(struct bsc_data *bsc)
|
|||
|
||||
LOGP(DINP, LOGL_NOTICE, "Using UDP MTP mode.\n");
|
||||
|
||||
/* setup SNMP first, it is blocking */
|
||||
bsc->udp_data.session = snmp_mtp_session_create(bsc->udp_ip);
|
||||
if (!bsc->udp_data.session)
|
||||
return -1;
|
||||
|
||||
if (link_global_init(&bsc->udp_data, bsc->src_port) != 0)
|
||||
if (link_global_init(&bsc->udp_data, bsc->udp_ip, bsc->src_port) != 0)
|
||||
return -1;
|
||||
|
||||
/* now connect to the transport */
|
||||
|
|
|
@ -41,39 +41,83 @@ static void add_pdu_var(netsnmp_pdu *pdu, const char *mib_name, int id, const ch
|
|||
}
|
||||
}
|
||||
|
||||
static void send_pdu(netsnmp_session *ss, netsnmp_pdu *pdu)
|
||||
static int link_up_cb(int op, netsnmp_session *ss,
|
||||
int reqid, netsnmp_pdu *pdu, void *data)
|
||||
{
|
||||
struct snmp_mtp_session *mtp = ss->myvoid;
|
||||
int link_index = (int) data;
|
||||
|
||||
if (mtp->last_up_req != reqid)
|
||||
return 0;
|
||||
|
||||
mtp->last_up_req = 0;
|
||||
snmp_mtp_callback(mtp, SNMP_LINK_UP,
|
||||
op == STAT_TIMEOUT ? SNMP_STATUS_TIMEOUT : SNMP_STATUS_OK,
|
||||
link_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_down_cb(int op, netsnmp_session *ss,
|
||||
int reqid, netsnmp_pdu *pdu, void *data)
|
||||
{
|
||||
struct snmp_mtp_session *mtp = ss->myvoid;
|
||||
int link_index = (int) data;
|
||||
|
||||
if (mtp->last_do_req != reqid)
|
||||
return 0;
|
||||
|
||||
mtp->last_do_req = 0;
|
||||
snmp_mtp_callback(mtp, SNMP_LINK_DOWN,
|
||||
op == STAT_TIMEOUT ? SNMP_STATUS_TIMEOUT : SNMP_STATUS_OK,
|
||||
link_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_pdu(netsnmp_session *ss, netsnmp_pdu *pdu, int kind, int link_id)
|
||||
{
|
||||
int status;
|
||||
netsnmp_pdu *response;
|
||||
netsnmp_callback cb;
|
||||
|
||||
status = snmp_synch_response(ss, pdu, &response);
|
||||
if (status == STAT_ERROR) {
|
||||
snmp_sess_perror("set failed", ss);
|
||||
} else if (status == STAT_TIMEOUT) {
|
||||
fprintf(stderr, "Timeout for SNMP.\n");
|
||||
cb = kind == SNMP_LINK_UP ? link_up_cb : link_down_cb;
|
||||
|
||||
status = snmp_async_send(ss, pdu, cb, (void *) link_id);
|
||||
if (status == 0) {
|
||||
snmp_log(LOG_ERR, "Failed to send async request.\n");
|
||||
snmp_free_pdu(pdu);
|
||||
}
|
||||
|
||||
if (response)
|
||||
snmp_free_pdu(response);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void snmp_mtp_start_c7_datalink(struct snmp_mtp_session *session, int link_id)
|
||||
{
|
||||
int status;
|
||||
netsnmp_pdu *pdu;
|
||||
pdu = snmp_pdu_create(SNMP_MSG_SET);
|
||||
|
||||
add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7DatalinkCommand", link_id, "nwc7DatalinkCmdPowerOn");
|
||||
add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7Mtp2Active", link_id, "true");
|
||||
send_pdu(session->ss, pdu);
|
||||
status = send_pdu(session->ss, pdu, SNMP_LINK_UP, link_id);
|
||||
|
||||
if (status == 0)
|
||||
snmp_mtp_callback(session, SNMP_LINK_UP, SNMP_STATUS_TIMEOUT, link_id);
|
||||
else
|
||||
session->last_up_req = status;
|
||||
|
||||
}
|
||||
|
||||
static void snmp_mtp_stop_c7_datalink(struct snmp_mtp_session *session, int link_id)
|
||||
{
|
||||
int status;
|
||||
netsnmp_pdu *pdu;
|
||||
pdu = snmp_pdu_create(SNMP_MSG_SET);
|
||||
|
||||
add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7Mtp2Active", link_id, "false");
|
||||
send_pdu(session->ss, pdu);
|
||||
status = send_pdu(session->ss, pdu, SNMP_LINK_DOWN, link_id);
|
||||
if (status == 0)
|
||||
snmp_mtp_callback(session, SNMP_LINK_DOWN, SNMP_STATUS_TIMEOUT, link_id);
|
||||
else
|
||||
session->last_do_req = status;
|
||||
}
|
||||
|
||||
struct snmp_mtp_session *snmp_mtp_session_create(char *host)
|
||||
|
@ -88,6 +132,7 @@ struct snmp_mtp_session *snmp_mtp_session_create(char *host)
|
|||
session->session.version = SNMP_VERSION_1;
|
||||
session->session.community = (unsigned char *) "private";
|
||||
session->session.community_len = strlen((const char *) session->session.community);
|
||||
session->session.myvoid = session;
|
||||
|
||||
session->ss = snmp_open(&session->session);
|
||||
if (!session->ss) {
|
||||
|
|
Reference in New Issue