blob: c5ac5da8b173ace0b5e259b4d76c0e83ca26dd0e [file] [log] [blame]
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +01001/* link management code */
2/*
3 * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
4 * (C) 2010-2011 by On-Waves
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <bsc_data.h>
24#include <cellmgr_debug.h>
25#include <mtp_data.h>
Holger Hans Peter Freytherddf8eae2011-01-22 17:36:01 +010026#include <mtp_pcap.h>
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +010027#include <snmp_mtp.h>
28
Holger Hans Peter Freyther644aafb2011-01-03 23:51:07 +010029#include <osmocore/talloc.h>
30
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +010031extern struct bsc_data bsc;
32
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010033int is_one_up(struct mtp_link_set *set)
34{
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +010035 struct mtp_link *entry;
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010036
37 llist_for_each_entry(entry, &set->links, entry)
38 if (entry->available)
39 return 1;
40 return 0;
41}
42
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +010043void mtp_link_down(struct mtp_link *link)
Holger Hans Peter Freytherc8405692011-01-02 20:24:08 +010044{
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010045 int one_up;
46 int was_up;
47
48 was_up = link->available;
49 link->available = 0;
Holger Hans Peter Freythera8ce0612011-01-20 16:30:24 +010050 link->was_up = 0;
Holger Hans Peter Freyther2d845fc2011-01-20 15:42:13 +010051 one_up = is_one_up(link->set);
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010052
53 /* our linkset is now unsuable */
54 if (was_up && !one_up)
Holger Hans Peter Freyther2d845fc2011-01-20 15:42:13 +010055 mtp_linkset_down(link->set);
Holger Hans Peter Freytherc8405692011-01-02 20:24:08 +010056 link->clear_queue(link);
Holger Hans Peter Freythera8ce0612011-01-20 16:30:24 +010057 mtp_link_stop_link_test(link);
Holger Hans Peter Freyther2d845fc2011-01-20 15:42:13 +010058 mtp_link_set_init_slc(link->set);
Holger Hans Peter Freytherc8405692011-01-02 20:24:08 +010059}
60
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +010061void mtp_link_up(struct mtp_link *link)
Holger Hans Peter Freytherc8405692011-01-02 20:24:08 +010062{
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010063 int one_up;
64
Holger Hans Peter Freyther309d79f2011-01-28 18:26:20 +010065 if (link->blocked) {
66 LOGP(DINP, LOGL_ERROR, "Ignoring link up on blocked link %s/%d.\n",
67 link->set->name, link->link_no);
68 return;
69 }
70
Holger Hans Peter Freyther2d845fc2011-01-20 15:42:13 +010071 one_up = is_one_up(link->set);
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010072 link->available = 1;
Holger Hans Peter Freythera8ce0612011-01-20 16:30:24 +010073 link->was_up = 0;
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010074
Holger Hans Peter Freyther2d845fc2011-01-20 15:42:13 +010075 mtp_link_set_init_slc(link->set);
Holger Hans Peter Freyther0f833b02011-01-04 13:33:57 +010076 if (!one_up)
Holger Hans Peter Freyther2d845fc2011-01-20 15:42:13 +010077 mtp_linkset_up(link->set);
Holger Hans Peter Freythera8ce0612011-01-20 16:30:24 +010078 else
79 mtp_link_start_link_test(link);
Holger Hans Peter Freytherc8405692011-01-02 20:24:08 +010080}
81
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +010082void mtp_link_restart(struct mtp_link *link)
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +010083{
84 LOGP(DINP, LOGL_ERROR, "Need to restart the SS7 link.\n");
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +010085 link->reset(link);
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +010086}
87
88static void start_rest(void *start)
89{
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +010090 struct mtp_link *data;
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +010091 bsc.setup = 1;
92
Holger Hans Peter Freythere86c02e2011-02-10 15:32:14 +010093 if (msc_init(&bsc.msc_forward, 1) != 0) {
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +010094 fprintf(stderr, "Failed to init MSC part.\n");
95 exit(3);
96 }
97
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +010098 llist_for_each_entry(data, &bsc.link_set->links, entry)
99 data->start(data);
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +0100100}
101
102int link_init(struct bsc_data *bsc)
103{
Holger Hans Peter Freytherc6bfa272011-01-22 17:06:34 +0100104 int i;
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +0100105 struct mtp_udp_link *lnk;
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +0100106
Holger Hans Peter Freyther644aafb2011-01-03 23:51:07 +0100107 bsc->link_set = mtp_link_set_alloc();
Holger Hans Peter Freyther38d936a2011-01-26 12:41:42 +0100108 bsc->link_set->name = talloc_strdup(bsc->link_set, "MTP");
Holger Hans Peter Freyther644aafb2011-01-03 23:51:07 +0100109 bsc->link_set->dpc = bsc->dpc;
110 bsc->link_set->opc = bsc->opc;
111 bsc->link_set->sccp_opc = bsc->sccp_opc > -1 ? bsc->sccp_opc : bsc->opc;
Holger Hans Peter Freytherd8a73e22011-01-17 22:37:11 +0100112 bsc->link_set->isup_opc = bsc->isup_opc > -1 ? bsc->isup_opc : bsc->opc;
Holger Hans Peter Freyther644aafb2011-01-03 23:51:07 +0100113 bsc->link_set->sltm_once = bsc->once;
114 bsc->link_set->ni = bsc->ni_ni;
115 bsc->link_set->spare = bsc->ni_spare;
116 bsc->link_set->bsc = bsc;
Holger Hans Peter Freytherf6375b42011-01-22 21:01:23 +0100117 bsc->link_set->pcap_fd = bsc->pcap_fd;
Holger Hans Peter Freyther644aafb2011-01-03 23:51:07 +0100118
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +0100119 if (!bsc->src_port) {
120 LOGP(DINP, LOGL_ERROR, "You need to set a UDP address.\n");
121 return -1;
122 }
123
124 LOGP(DINP, LOGL_NOTICE, "Using UDP MTP mode.\n");
125
Holger Hans Peter Freyther3a1c0af2011-01-24 20:21:11 +0100126 if (link_global_init(&bsc->udp_data, bsc->src_port) != 0)
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +0100127 return -1;
128
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +0100129
Holger Hans Peter Freytherc6bfa272011-01-22 17:06:34 +0100130 for (i = 1; i <= bsc->udp_nr_links; ++i) {
131 lnk = talloc_zero(bsc->link_set, struct mtp_udp_link);
Holger Hans Peter Freytherf6375b42011-01-22 21:01:23 +0100132 lnk->base.pcap_fd = -1;
Holger Hans Peter Freytherc6bfa272011-01-22 17:06:34 +0100133 lnk->bsc = bsc;
134 lnk->data = &bsc->udp_data;
135 lnk->link_index = i;
136 lnk->reset_timeout = bsc->udp_reset_timeout;
137 mtp_link_set_add_link(bsc->link_set, (struct mtp_link *) lnk);
138
139
140 /* now connect to the transport */
141 if (link_udp_init(lnk, bsc->udp_ip, bsc->udp_port) != 0)
142 return -1;
143
144 /*
145 * We will ask the MTP link to be taken down for two
146 * timeouts of the BSC to make sure we are missing the
147 * SLTM and it begins a reset. Then we will take it up
148 * again and do the usual business.
149 */
Holger Hans Peter Freyther3a1c0af2011-01-24 20:21:11 +0100150 snmp_mtp_deactivate(lnk->session,
Holger Hans Peter Freytherc6bfa272011-01-22 17:06:34 +0100151 lnk->link_index);
152 bsc->start_timer.cb = start_rest;
153 bsc->start_timer.data = &bsc;
154 bsc_schedule_timer(&bsc->start_timer, lnk->reset_timeout, 0);
Holger Hans Peter Freyther38d936a2011-01-26 12:41:42 +0100155 LOGP(DMSC, LOGL_NOTICE,
Holger Hans Peter Freytherd3f412b2011-01-28 18:52:16 +0100156 "Forcing link alignment on %s/%d.\n",
Holger Hans Peter Freyther38d936a2011-01-26 12:41:42 +0100157 lnk->base.set->name, lnk->base.link_no);
Holger Hans Peter Freytherc6bfa272011-01-22 17:06:34 +0100158 }
Holger Hans Peter Freythera99b04b2011-01-02 11:23:54 +0100159
160 return 0;
161}
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +0100162
163int link_shutdown_all(struct mtp_link_set *set)
164{
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +0100165 struct mtp_link *lnk;
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +0100166
167 llist_for_each_entry(lnk, &set->links, entry)
168 lnk->shutdown(lnk);
169 return 0;
170}
171
172int link_reset_all(struct mtp_link_set *set)
173{
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +0100174 struct mtp_link *lnk;
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +0100175
176 llist_for_each_entry(lnk, &set->links, entry)
177 lnk->reset(lnk);
178 return 0;
179}
180
181int link_clear_all(struct mtp_link_set *set)
182{
Holger Hans Peter Freyther0e2f9112011-01-17 11:54:39 +0100183 struct mtp_link *lnk;
Holger Hans Peter Freytherfe72c162011-01-04 13:21:52 +0100184
185 llist_for_each_entry(lnk, &set->links, entry)
186 lnk->clear_queue(lnk);
187 return 0;
188}
Holger Hans Peter Freytherddf8eae2011-01-22 17:36:01 +0100189
Holger Hans Peter Freyther36260e92011-01-22 17:37:56 +0100190int mtp_handle_pcap(struct mtp_link *link, int dir, const uint8_t *data, int len)
Holger Hans Peter Freytherddf8eae2011-01-22 17:36:01 +0100191{
Holger Hans Peter Freyther8ade9b72011-01-23 16:18:18 +0100192 if (link->pcap_fd >= 0)
Holger Hans Peter Freytherf6375b42011-01-22 21:01:23 +0100193 mtp_pcap_write_msu(link->pcap_fd, data, len);
Holger Hans Peter Freyther8ade9b72011-01-23 16:18:18 +0100194 if (link->set->pcap_fd >= 0)
Holger Hans Peter Freytherf6375b42011-01-22 21:01:23 +0100195 mtp_pcap_write_msu(link->set->pcap_fd, data, len);
Holger Hans Peter Freyther16b07c62011-01-22 23:19:27 +0100196
197 /* This might be too expensive? */
198 LOGP(DPCAP, LOGL_NOTICE, "Packet: %s\n", hexdump(data, len));
Holger Hans Peter Freytherddf8eae2011-01-22 17:36:01 +0100199 return 0;
200}