aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/bsc/paging.h
blob: 819f47827b460f8c6acc9c53be527a258dfb45a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Paging helper and manager.... */
/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef PAGING_H
#define PAGING_H

#include <stdlib.h>
#include <string.h>

#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>

#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/bsc_subscriber.h>
#include <osmocom/bsc/bsc_msc_data.h>

struct bsc_msc_data;

#define LOG_PAGING(PARAMS, SUBSYS, LEVEL, fmt, args...) \
	LOGP(SUBSYS, LEVEL, "(msc=%d) Paging%s: %s: " fmt, \
	     (PARAMS)->msc ? (PARAMS)->msc->nr : -1, \
	     (PARAMS)->reason == BSC_PAGING_FOR_LCS ? " for LCS" : "", \
	     bsc_subscr_name((PARAMS)->bsub), \
	     ##args)

#define LOG_PAGING_BTS(PARAMS, BTS, SUBSYS, LEVEL, fmt, args...) \
	LOG_PAGING(PARAMS, SUBSYS, LEVEL, "(bts=%u) " fmt, (BTS) ? (BTS)->nr : 255, ##args)

#define BSUB_USE_PAGING_START "paging-start"
#define BSUB_USE_PAGING_REQUEST "paging-req"

/* Bitmask of reasons for Paging. Each individual Paging via bsc_paging_start() typically has only one of these reasons
 * set, but when a subscriber responds, we need to aggregate all pending Paging reasons (by bitwise-OR). */
enum bsc_paging_reason {
	BSC_PAGING_NONE = 0,
	BSC_PAGING_FROM_CN = 0x1,
	BSC_PAGING_FOR_LCS = 0x2,
};

struct bsc_paging_params {
	enum bsc_paging_reason reason;
	struct bsc_msc_data *msc;
	struct bsc_subscr *bsub;
	uint32_t tmsi;
	struct osmo_mobile_identity imsi;
	uint8_t chan_needed;
	struct gsm0808_cell_id_list2 cil;
};

/**
 * A pending paging request
 */
struct gsm_paging_request {
	/* list_head for list of all paging requests */
	struct llist_head entry;
	/* the subscriber which we're paging. Later gsm_paging_request
	 * should probably become a part of the bsc_subsrc struct? */
	struct bsc_subscr *bsub;
	/* back-pointer to the BTS on which we are paging */
	struct gsm_bts *bts;
	/* what kind of channel type do we ask the MS to establish */
	int chan_type;
	/* paging group of the subscriber: */
	uint8_t pgroup;

	/* Timer 3113: how long do we try to page? */
	struct osmo_timer_list T3113;

	/* How often did we ask the BTS to page? */
	int attempts;
	/* Timestamp of last time the subscriber was paged */
	struct timespec last_attempt_ts;

	/* MSC that has issued this paging */
	struct bsc_msc_data *msc;

	enum bsc_paging_reason reason;
};

/*
 * This keeps track of the paging status of one BTS. It
 * includes a number of pending requests, a back pointer
 * to the gsm_bts, a timer and some more state.
 */
struct gsm_bts_paging_state {
	/* pending requests */
	struct llist_head pending_requests;
	/* Number of requests in pending_requests_len */
	unsigned int pending_requests_len;
	struct gsm_bts *bts;

	struct osmo_timer_list work_timer;
	struct osmo_timer_list credit_timer;

	/* Last time paging worker was triggered */
	struct timespec last_sched_ts;

	/* free chans needed */
	int free_chans_need;

	/* load */
	uint16_t available_slots;
};

void paging_init(struct gsm_bts *bts);
void paging_destructor(struct gsm_bts *bts);

/* schedule paging request */
int paging_request_bts(const struct bsc_paging_params *params, struct gsm_bts *bts);

int paging_request_stop(struct bsc_msc_data **msc_p, enum bsc_paging_reason *reasons_p,
			struct gsm_bts *bts, struct bsc_subscr *bsub);
int paging_request_cancel(struct bsc_subscr *bsub, enum bsc_paging_reason reasons);

/* update paging load */
void paging_update_buffer_space(struct gsm_bts *bts, uint16_t);

/* pending paging requests */
unsigned int paging_pending_requests_nr(struct gsm_bts *bts);

void paging_flush_bts(struct gsm_bts *bts, struct bsc_msc_data *msc);
void paging_flush_network(struct gsm_network *net, struct bsc_msc_data *msc);

uint16_t paging_estimate_available_slots(struct gsm_bts *bts, unsigned int time_span_s);

int bsc_paging_start(struct bsc_paging_params *params);
#endif