1 /* GPRS BSSGP protocol implementation as per 3GPP TS 08.18 */
3 /* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
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 Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * o properly count incoming BVC-RESET packets in counter group
22 * o set log context as early as possible for outgoing packets
28 #include <netinet/in.h>
30 #include <osmocom/core/msgb.h>
31 #include <osmocom/gsm/tlv.h>
32 #include <osmocom/core/talloc.h>
33 #include <osmocom/core/rate_ctr.h>
35 #include <openbsc/debug.h>
36 #include <openbsc/gsm_data.h>
37 #include <openbsc/gsm_04_08_gprs.h>
39 #include <osmocom/gprs/gprs_bssgp.h>
40 #include <osmocom/gprs/gprs_ns.h>
42 #include <openbsc/gprs_gmm.h>
44 void *bssgp_tall_ctx
= NULL
;
46 static const struct rate_ctr_desc bssgp_ctr_description
[] = {
47 { "packets.in", "Packets at BSSGP Level ( In)" },
48 { "packets.out","Packets at BSSGP Level (Out)" },
49 { "bytes.in", "Bytes at BSSGP Level ( In)" },
50 { "bytes.out", "Bytes at BSSGP Level (Out)" },
51 { "blocked", "BVC Blocking count" },
52 { "discarded", "BVC LLC Discarded count" },
55 static const struct rate_ctr_group_desc bssgp_ctrg_desc
= {
56 .group_name_prefix
= "bssgp.bss_ctx",
57 .group_description
= "BSSGP Peer Statistics",
58 .num_ctr
= ARRAY_SIZE(bssgp_ctr_description
),
59 .ctr_desc
= bssgp_ctr_description
,
62 LLIST_HEAD(bssgp_bvc_ctxts
);
64 /* Find a BTS Context based on parsed RA ID and Cell ID */
65 struct bssgp_bvc_ctx
*btsctx_by_raid_cid(const struct gprs_ra_id
*raid
, uint16_t cid
)
67 struct bssgp_bvc_ctx
*bctx
;
69 llist_for_each_entry(bctx
, &bssgp_bvc_ctxts
, list
) {
70 if (!memcmp(&bctx
->ra_id
, raid
, sizeof(bctx
->ra_id
)) &&
77 /* Find a BTS context based on BVCI+NSEI tuple */
78 struct bssgp_bvc_ctx
*btsctx_by_bvci_nsei(uint16_t bvci
, uint16_t nsei
)
80 struct bssgp_bvc_ctx
*bctx
;
82 llist_for_each_entry(bctx
, &bssgp_bvc_ctxts
, list
) {
83 if (bctx
->nsei
== nsei
&& bctx
->bvci
== bvci
)
89 struct bssgp_bvc_ctx
*btsctx_alloc(uint16_t bvci
, uint16_t nsei
)
91 struct bssgp_bvc_ctx
*ctx
;
93 ctx
= talloc_zero(bssgp_tall_ctx
, struct bssgp_bvc_ctx
);
98 /* FIXME: BVCI is not unique, only BVCI+NSEI ?!? */
99 ctx
->ctrg
= rate_ctr_group_alloc(ctx
, &bssgp_ctrg_desc
, bvci
);
101 llist_add(&ctx
->list
, &bssgp_bvc_ctxts
);
106 /* Chapter 10.4.5: Flow Control BVC ACK */
107 static int bssgp_tx_fc_bvc_ack(uint16_t nsei
, uint8_t tag
, uint16_t ns_bvci
)
109 struct msgb
*msg
= bssgp_msgb_alloc();
110 struct bssgp_normal_hdr
*bgph
=
111 (struct bssgp_normal_hdr
*) msgb_put(msg
, sizeof(*bgph
));
113 msgb_nsei(msg
) = nsei
;
114 msgb_bvci(msg
) = ns_bvci
;
116 bgph
->pdu_type
= BSSGP_PDUT_FLOW_CONTROL_BVC_ACK
;
117 msgb_tvlv_put(msg
, BSSGP_IE_TAG
, 1, &tag
);
119 return gprs_ns_sendmsg(bssgp_nsi
, msg
);
122 /* 10.3.7 SUSPEND-ACK PDU */
123 int bssgp_tx_suspend_ack(uint16_t nsei
, uint32_t tlli
,
124 const struct gprs_ra_id
*ra_id
, uint8_t suspend_ref
)
126 struct msgb
*msg
= bssgp_msgb_alloc();
127 struct bssgp_normal_hdr
*bgph
=
128 (struct bssgp_normal_hdr
*) msgb_put(msg
, sizeof(*bgph
));
132 msgb_nsei(msg
) = nsei
;
133 msgb_bvci(msg
) = 0; /* Signalling */
134 bgph
->pdu_type
= BSSGP_PDUT_SUSPEND_ACK
;
137 msgb_tvlv_put(msg
, BSSGP_IE_TLLI
, 4, (uint8_t *) &_tlli
);
138 gsm48_construct_ra(ra
, ra_id
);
139 msgb_tvlv_put(msg
, BSSGP_IE_ROUTEING_AREA
, 6, ra
);
140 msgb_tvlv_put(msg
, BSSGP_IE_SUSPEND_REF_NR
, 1, &suspend_ref
);
142 return gprs_ns_sendmsg(bssgp_nsi
, msg
);
145 /* 10.3.8 SUSPEND-NACK PDU */
146 int bssgp_tx_suspend_nack(uint16_t nsei
, uint32_t tlli
,
147 const struct gprs_ra_id
*ra_id
,
150 struct msgb
*msg
= bssgp_msgb_alloc();
151 struct bssgp_normal_hdr
*bgph
=
152 (struct bssgp_normal_hdr
*) msgb_put(msg
, sizeof(*bgph
));
156 msgb_nsei(msg
) = nsei
;
157 msgb_bvci(msg
) = 0; /* Signalling */
158 bgph
->pdu_type
= BSSGP_PDUT_SUSPEND_NACK
;
161 msgb_tvlv_put(msg
, BSSGP_IE_TLLI
, 4, (uint8_t *) &_tlli
);
162 gsm48_construct_ra(ra
, ra_id
);
163 msgb_tvlv_put(msg
, BSSGP_IE_ROUTEING_AREA
, 6, ra
);
165 msgb_tvlv_put(msg
, BSSGP_IE_CAUSE
, 1, cause
);
167 return gprs_ns_sendmsg(bssgp_nsi
, msg
);
170 /* 10.3.10 RESUME-ACK PDU */
171 int bssgp_tx_resume_ack(uint16_t nsei
, uint32_t tlli
,
172 const struct gprs_ra_id
*ra_id
)
174 struct msgb
*msg
= bssgp_msgb_alloc();
175 struct bssgp_normal_hdr
*bgph
=
176 (struct bssgp_normal_hdr
*) msgb_put(msg
, sizeof(*bgph
));
180 msgb_nsei(msg
) = nsei
;
181 msgb_bvci(msg
) = 0; /* Signalling */
182 bgph
->pdu_type
= BSSGP_PDUT_RESUME_ACK
;
185 msgb_tvlv_put(msg
, BSSGP_IE_TLLI
, 4, (uint8_t *) &_tlli
);
186 gsm48_construct_ra(ra
, ra_id
);
187 msgb_tvlv_put(msg
, BSSGP_IE_ROUTEING_AREA
, 6, ra
);
189 return gprs_ns_sendmsg(bssgp_nsi
, msg
);
192 /* 10.3.11 RESUME-NACK PDU */
193 int bssgp_tx_resume_nack(uint16_t nsei
, uint32_t tlli
,
194 const struct gprs_ra_id
*ra_id
, uint8_t *cause
)
196 struct msgb
*msg
= bssgp_msgb_alloc();
197 struct bssgp_normal_hdr
*bgph
=
198 (struct bssgp_normal_hdr
*) msgb_put(msg
, sizeof(*bgph
));
202 msgb_nsei(msg
) = nsei
;
203 msgb_bvci(msg
) = 0; /* Signalling */
204 bgph
->pdu_type
= BSSGP_PDUT_SUSPEND_NACK
;
207 msgb_tvlv_put(msg
, BSSGP_IE_TLLI
, 4, (uint8_t *) &_tlli
);
208 gsm48_construct_ra(ra
, ra_id
);
209 msgb_tvlv_put(msg
, BSSGP_IE_ROUTEING_AREA
, 6, ra
);
211 msgb_tvlv_put(msg
, BSSGP_IE_CAUSE
, 1, cause
);
213 return gprs_ns_sendmsg(bssgp_nsi
, msg
);
216 uint16_t bssgp_parse_cell_id(struct gprs_ra_id
*raid
, const uint8_t *buf
)
219 gsm48_parse_ra(raid
, buf
);
221 return ntohs(*(uint16_t *) (buf
+6));
224 int bssgp_create_cell_id(uint8_t *buf
, const struct gprs_ra_id
*raid
,
227 uint16_t *out_cid
= (uint16_t *) (buf
+ 6);
229 gsm48_construct_ra(buf
, raid
);
231 *out_cid
= htons(cid
);
236 /* Chapter 8.4 BVC-Reset Procedure */
237 static int bssgp_rx_bvc_reset(struct msgb
*msg
, struct tlv_parsed
*tp
,
240 struct bssgp_bvc_ctx
*bctx
;
241 uint16_t nsei
= msgb_nsei(msg
);
245 bvci
= ntohs(*(uint16_t *)TLVP_VAL(tp
, BSSGP_IE_BVCI
));
246 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx RESET cause=%s\n", bvci
,
247 bssgp_cause_str(*TLVP_VAL(tp
, BSSGP_IE_CAUSE
)));
249 /* look-up or create the BTS context for this BVC */
250 bctx
= btsctx_by_bvci_nsei(bvci
, nsei
);
252 bctx
= btsctx_alloc(bvci
, nsei
);
254 /* As opposed to NS-VCs, BVCs are NOT blocked after RESET */
255 bctx
->state
&= ~BVC_S_BLOCKED
;
257 /* When we receive a BVC-RESET PDU (at least of a PTP BVCI), the BSS
258 * informs us about its RAC + Cell ID, so we can create a mapping */
259 if (bvci
!= 0 && bvci
!= 1) {
260 if (!TLVP_PRESENT(tp
, BSSGP_IE_CELL_ID
)) {
261 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP BVCI=%u Rx RESET "
262 "missing mandatory IE\n", bvci
);
265 /* actually extract RAC / CID */
266 bctx
->cell_id
= bssgp_parse_cell_id(&bctx
->ra_id
,
267 TLVP_VAL(tp
, BSSGP_IE_CELL_ID
));
268 LOGP(DBSSGP
, LOGL_NOTICE
, "Cell %u-%u-%u-%u CI %u on BVCI %u\n",
269 bctx
->ra_id
.mcc
, bctx
->ra_id
.mnc
, bctx
->ra_id
.lac
,
270 bctx
->ra_id
.rac
, bctx
->cell_id
, bvci
);
273 /* Acknowledge the RESET to the BTS */
274 rc
= bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_RESET_ACK
,
275 nsei
, bvci
, ns_bvci
);
279 static int bssgp_rx_bvc_block(struct msgb
*msg
, struct tlv_parsed
*tp
)
282 struct bssgp_bvc_ctx
*ptp_ctx
;
284 bvci
= ntohs(*(uint16_t *)TLVP_VAL(tp
, BSSGP_IE_BVCI
));
285 if (bvci
== BVCI_SIGNALLING
) {
286 /* 8.3.2: Signalling BVC shall never be blocked */
287 LOGP(DBSSGP
, LOGL_ERROR
, "NSEI=%u/BVCI=%u "
288 "received block for signalling BVC!?!\n",
289 msgb_nsei(msg
), msgb_bvci(msg
));
293 LOGP(DBSSGP
, LOGL_INFO
, "BSSGP Rx BVCI=%u BVC-BLOCK\n", bvci
);
295 ptp_ctx
= btsctx_by_bvci_nsei(bvci
, msgb_nsei(msg
));
297 return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI
, &bvci
, msg
);
299 ptp_ctx
->state
|= BVC_S_BLOCKED
;
300 rate_ctr_inc(&ptp_ctx
->ctrg
->ctr
[BSSGP_CTR_BLOCKED
]);
302 /* FIXME: Send NM_BVC_BLOCK.ind to NM */
304 /* We always acknowledge the BLOCKing */
305 return bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK_ACK
, msgb_nsei(msg
),
306 bvci
, msgb_bvci(msg
));
309 static int bssgp_rx_bvc_unblock(struct msgb
*msg
, struct tlv_parsed
*tp
)
312 struct bssgp_bvc_ctx
*ptp_ctx
;
314 bvci
= ntohs(*(uint16_t *)TLVP_VAL(tp
, BSSGP_IE_BVCI
));
315 if (bvci
== BVCI_SIGNALLING
) {
316 /* 8.3.2: Signalling BVC shall never be blocked */
317 LOGP(DBSSGP
, LOGL_ERROR
, "NSEI=%u/BVCI=%u "
318 "received unblock for signalling BVC!?!\n",
319 msgb_nsei(msg
), msgb_bvci(msg
));
323 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx BVC-UNBLOCK\n", bvci
);
325 ptp_ctx
= btsctx_by_bvci_nsei(bvci
, msgb_nsei(msg
));
327 return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI
, &bvci
, msg
);
329 ptp_ctx
->state
&= ~BVC_S_BLOCKED
;
331 /* FIXME: Send NM_BVC_UNBLOCK.ind to NM */
333 /* We always acknowledge the unBLOCKing */
334 return bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_UNBLOCK_ACK
, msgb_nsei(msg
),
335 bvci
, msgb_bvci(msg
));
338 /* Uplink unit-data */
339 static int bssgp_rx_ul_ud(struct msgb
*msg
, struct tlv_parsed
*tp
,
340 struct bssgp_bvc_ctx
*ctx
)
342 struct bssgp_ud_hdr
*budh
= (struct bssgp_ud_hdr
*) msgb_bssgph(msg
);
344 /* extract TLLI and parse TLV IEs */
345 msgb_tlli(msg
) = ntohl(budh
->tlli
);
347 DEBUGP(DBSSGP
, "BSSGP TLLI=0x%08x Rx UPLINK-UNITDATA\n", msgb_tlli(msg
));
349 /* Cell ID and LLC_PDU are the only mandatory IE */
350 if (!TLVP_PRESENT(tp
, BSSGP_IE_CELL_ID
) ||
351 !TLVP_PRESENT(tp
, BSSGP_IE_LLC_PDU
)) {
352 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP TLLI=0x%08x Rx UL-UD "
353 "missing mandatory IE\n", msgb_tlli(msg
));
354 return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE
, NULL
, msg
);
357 /* store pointer to LLC header and CELL ID in msgb->cb */
358 msgb_llch(msg
) = (uint8_t *) TLVP_VAL(tp
, BSSGP_IE_LLC_PDU
);
359 msgb_bcid(msg
) = (uint8_t *) TLVP_VAL(tp
, BSSGP_IE_CELL_ID
);
361 return gprs_llc_rcvmsg(msg
, tp
);
364 static int bssgp_rx_suspend(struct msgb
*msg
, struct tlv_parsed
*tp
,
365 struct bssgp_bvc_ctx
*ctx
)
367 struct bssgp_normal_hdr
*bgph
=
368 (struct bssgp_normal_hdr
*) msgb_bssgph(msg
);
369 struct gprs_ra_id raid
;
373 if (!TLVP_PRESENT(tp
, BSSGP_IE_TLLI
) ||
374 !TLVP_PRESENT(tp
, BSSGP_IE_ROUTEING_AREA
)) {
375 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP BVCI=%u Rx SUSPEND "
376 "missing mandatory IE\n", ctx
->bvci
);
377 return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE
, NULL
, msg
);
380 tlli
= ntohl(*(uint32_t *)TLVP_VAL(tp
, BSSGP_IE_TLLI
));
382 DEBUGP(DBSSGP
, "BSSGP BVCI=%u TLLI=0x%08x Rx SUSPEND\n",
385 gsm48_parse_ra(&raid
, TLVP_VAL(tp
, BSSGP_IE_ROUTEING_AREA
));
387 /* Inform GMM about the SUSPEND request */
388 rc
= gprs_gmm_rx_suspend(&raid
, tlli
);
390 return bssgp_tx_suspend_nack(msgb_nsei(msg
), tlli
, &raid
, NULL
);
392 bssgp_tx_suspend_ack(msgb_nsei(msg
), tlli
, &raid
, 0);
397 static int bssgp_rx_resume(struct msgb
*msg
, struct tlv_parsed
*tp
,
398 struct bssgp_bvc_ctx
*ctx
)
400 struct bssgp_normal_hdr
*bgph
=
401 (struct bssgp_normal_hdr
*) msgb_bssgph(msg
);
402 struct gprs_ra_id raid
;
407 if (!TLVP_PRESENT(tp
, BSSGP_IE_TLLI
) ||
408 !TLVP_PRESENT(tp
, BSSGP_IE_ROUTEING_AREA
) ||
409 !TLVP_PRESENT(tp
, BSSGP_IE_SUSPEND_REF_NR
)) {
410 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP BVCI=%u Rx RESUME "
411 "missing mandatory IE\n", ctx
->bvci
);
412 return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE
, NULL
, msg
);
415 tlli
= ntohl(*(uint32_t *)TLVP_VAL(tp
, BSSGP_IE_TLLI
));
416 suspend_ref
= *TLVP_VAL(tp
, BSSGP_IE_SUSPEND_REF_NR
);
418 DEBUGP(DBSSGP
, "BSSGP BVCI=%u TLLI=0x%08x Rx RESUME\n", ctx
->bvci
, tlli
);
420 gsm48_parse_ra(&raid
, TLVP_VAL(tp
, BSSGP_IE_ROUTEING_AREA
));
422 /* Inform GMM about the RESUME request */
423 rc
= gprs_gmm_rx_resume(&raid
, tlli
, suspend_ref
);
425 return bssgp_tx_resume_nack(msgb_nsei(msg
), tlli
, &raid
,
428 bssgp_tx_resume_ack(msgb_nsei(msg
), tlli
, &raid
);
433 static int bssgp_rx_llc_disc(struct msgb
*msg
, struct tlv_parsed
*tp
,
434 struct bssgp_bvc_ctx
*ctx
)
438 if (!TLVP_PRESENT(tp
, BSSGP_IE_TLLI
) ||
439 !TLVP_PRESENT(tp
, BSSGP_IE_LLC_FRAMES_DISCARDED
) ||
440 !TLVP_PRESENT(tp
, BSSGP_IE_BVCI
) ||
441 !TLVP_PRESENT(tp
, BSSGP_IE_NUM_OCT_AFF
)) {
442 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP BVCI=%u Rx LLC DISCARDED "
443 "missing mandatory IE\n", ctx
->bvci
);
446 if (TLVP_PRESENT(tp
, BSSGP_IE_TLLI
))
447 tlli
= ntohl(*(uint32_t *)TLVP_VAL(tp
, BSSGP_IE_TLLI
));
449 DEBUGP(DBSSGP
, "BSSGP BVCI=%u TLLI=%08x Rx LLC DISCARDED\n",
452 rate_ctr_inc(&ctx
->ctrg
->ctr
[BSSGP_CTR_DISCARDED
]);
454 /* FIXME: send NM_LLC_DISCARDED to NM */
458 static int bssgp_rx_fc_bvc(struct msgb
*msg
, struct tlv_parsed
*tp
,
459 struct bssgp_bvc_ctx
*bctx
)
462 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx Flow Control BVC\n",
465 if (!TLVP_PRESENT(tp
, BSSGP_IE_TAG
) ||
466 !TLVP_PRESENT(tp
, BSSGP_IE_BVC_BUCKET_SIZE
) ||
467 !TLVP_PRESENT(tp
, BSSGP_IE_BUCKET_LEAK_RATE
) ||
468 !TLVP_PRESENT(tp
, BSSGP_IE_BMAX_DEFAULT_MS
) ||
469 !TLVP_PRESENT(tp
, BSSGP_IE_R_DEFAULT_MS
)) {
470 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP BVCI=%u Rx FC BVC "
471 "missing mandatory IE\n", bctx
->bvci
);
472 return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE
, NULL
, msg
);
475 /* FIXME: actually implement flow control */
477 /* Send FLOW_CONTROL_BVC_ACK */
478 return bssgp_tx_fc_bvc_ack(msgb_nsei(msg
), *TLVP_VAL(tp
, BSSGP_IE_TAG
),
482 /* Receive a BSSGP PDU from a BSS on a PTP BVCI */
483 static int gprs_bssgp_rx_ptp(struct msgb
*msg
, struct tlv_parsed
*tp
,
484 struct bssgp_bvc_ctx
*bctx
)
486 struct bssgp_normal_hdr
*bgph
=
487 (struct bssgp_normal_hdr
*) msgb_bssgph(msg
);
488 uint8_t pdu_type
= bgph
->pdu_type
;
491 /* If traffic is received on a BVC that is marked as blocked, the
492 * received PDU shall not be accepted and a STATUS PDU (Cause value:
493 * BVC Blocked) shall be sent to the peer entity on the signalling BVC */
494 if (bctx
->state
& BVC_S_BLOCKED
&& pdu_type
!= BSSGP_PDUT_STATUS
) {
495 uint16_t bvci
= msgb_bvci(msg
);
496 return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED
, &bvci
, msg
);
500 case BSSGP_PDUT_UL_UNITDATA
:
501 /* some LLC data from the MS */
502 rc
= bssgp_rx_ul_ud(msg
, tp
, bctx
);
504 case BSSGP_PDUT_RA_CAPABILITY
:
505 /* BSS requests RA capability or IMSI */
506 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx RA CAPABILITY UPDATE\n",
508 /* FIXME: send GMM_RA_CAPABILITY_UPDATE.ind to GMM */
509 /* FIXME: send RA_CAPA_UPDATE_ACK */
511 case BSSGP_PDUT_RADIO_STATUS
:
512 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx RADIO STATUS\n", bctx
->bvci
);
513 /* BSS informs us of some exception */
514 /* FIXME: send GMM_RADIO_STATUS.ind to GMM */
516 case BSSGP_PDUT_FLOW_CONTROL_BVC
:
517 /* BSS informs us of available bandwidth in Gb interface */
518 rc
= bssgp_rx_fc_bvc(msg
, tp
, bctx
);
520 case BSSGP_PDUT_FLOW_CONTROL_MS
:
521 /* BSS informs us of available bandwidth to one MS */
522 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx Flow Control MS\n",
524 /* FIXME: actually implement flow control */
525 /* FIXME: Send FLOW_CONTROL_MS_ACK */
527 case BSSGP_PDUT_STATUS
:
528 /* Some exception has occurred */
529 /* FIXME: send NM_STATUS.ind to NM */
530 case BSSGP_PDUT_DOWNLOAD_BSS_PFC
:
531 case BSSGP_PDUT_CREATE_BSS_PFC_ACK
:
532 case BSSGP_PDUT_CREATE_BSS_PFC_NACK
:
533 case BSSGP_PDUT_MODIFY_BSS_PFC
:
534 case BSSGP_PDUT_DELETE_BSS_PFC_ACK
:
535 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx PDU type 0x%02x not [yet] "
536 "implemented\n", bctx
->bvci
, pdu_type
);
537 rc
= bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT
, NULL
, msg
);
539 /* those only exist in the SGSN -> BSS direction */
540 case BSSGP_PDUT_DL_UNITDATA
:
541 case BSSGP_PDUT_PAGING_PS
:
542 case BSSGP_PDUT_PAGING_CS
:
543 case BSSGP_PDUT_RA_CAPA_UPDATE_ACK
:
544 case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK
:
545 case BSSGP_PDUT_FLOW_CONTROL_MS_ACK
:
546 DEBUGP(DBSSGP
, "BSSGP BVCI=%u PDU type 0x%02x only exists "
547 "in DL\n", bctx
->bvci
, pdu_type
);
548 bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC
, NULL
, msg
);
552 DEBUGP(DBSSGP
, "BSSGP BVCI=%u PDU type 0x%02x unknown\n",
553 bctx
->bvci
, pdu_type
);
554 rc
= bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC
, NULL
, msg
);
561 /* Receive a BSSGP PDU from a BSS on a SIGNALLING BVCI */
562 static int gprs_bssgp_rx_sign(struct msgb
*msg
, struct tlv_parsed
*tp
,
563 struct bssgp_bvc_ctx
*bctx
)
565 struct bssgp_normal_hdr
*bgph
=
566 (struct bssgp_normal_hdr
*) msgb_bssgph(msg
);
567 uint8_t pdu_type
= bgph
->pdu_type
;
569 uint16_t ns_bvci
= msgb_bvci(msg
);
572 switch (bgph
->pdu_type
) {
573 case BSSGP_PDUT_SUSPEND
:
574 /* MS wants to suspend */
575 rc
= bssgp_rx_suspend(msg
, tp
, bctx
);
577 case BSSGP_PDUT_RESUME
:
578 /* MS wants to resume */
579 rc
= bssgp_rx_resume(msg
, tp
, bctx
);
581 case BSSGP_PDUT_FLUSH_LL_ACK
:
582 /* BSS informs us it has performed LL FLUSH */
583 DEBUGP(DBSSGP
, "BSSGP Rx BVCI=%u FLUSH LL ACK\n", bctx
->bvci
);
584 /* FIXME: send NM_FLUSH_LL.res to NM */
586 case BSSGP_PDUT_LLC_DISCARD
:
587 /* BSS informs that some LLC PDU's have been discarded */
588 rc
= bssgp_rx_llc_disc(msg
, tp
, bctx
);
590 case BSSGP_PDUT_BVC_BLOCK
:
591 /* BSS tells us that BVC shall be blocked */
592 if (!TLVP_PRESENT(tp
, BSSGP_IE_BVCI
) ||
593 !TLVP_PRESENT(tp
, BSSGP_IE_CAUSE
)) {
594 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP Rx BVC-BLOCK "
595 "missing mandatory IE\n");
598 rc
= bssgp_rx_bvc_block(msg
, tp
);
600 case BSSGP_PDUT_BVC_UNBLOCK
:
601 /* BSS tells us that BVC shall be unblocked */
602 if (!TLVP_PRESENT(tp
, BSSGP_IE_BVCI
)) {
603 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP Rx BVC-UNBLOCK "
604 "missing mandatory IE\n");
607 rc
= bssgp_rx_bvc_unblock(msg
, tp
);
609 case BSSGP_PDUT_BVC_RESET
:
610 /* BSS tells us that BVC init is required */
611 if (!TLVP_PRESENT(tp
, BSSGP_IE_BVCI
) ||
612 !TLVP_PRESENT(tp
, BSSGP_IE_CAUSE
)) {
613 LOGP(DBSSGP
, LOGL_ERROR
, "BSSGP Rx BVC-RESET "
614 "missing mandatory IE\n");
617 rc
= bssgp_rx_bvc_reset(msg
, tp
, ns_bvci
);
619 case BSSGP_PDUT_STATUS
:
620 /* Some exception has occurred */
621 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx BVC STATUS\n", bctx
->bvci
);
622 /* FIXME: send NM_STATUS.ind to NM */
624 /* those only exist in the SGSN -> BSS direction */
625 case BSSGP_PDUT_PAGING_PS
:
626 case BSSGP_PDUT_PAGING_CS
:
627 case BSSGP_PDUT_SUSPEND_ACK
:
628 case BSSGP_PDUT_SUSPEND_NACK
:
629 case BSSGP_PDUT_RESUME_ACK
:
630 case BSSGP_PDUT_RESUME_NACK
:
631 case BSSGP_PDUT_FLUSH_LL
:
632 case BSSGP_PDUT_BVC_BLOCK_ACK
:
633 case BSSGP_PDUT_BVC_UNBLOCK_ACK
:
634 case BSSGP_PDUT_SGSN_INVOKE_TRACE
:
635 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx PDU type 0x%02x only exists "
636 "in DL\n", bctx
->bvci
, pdu_type
);
637 bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC
, NULL
, msg
);
641 DEBUGP(DBSSGP
, "BSSGP BVCI=%u Rx PDU type 0x%02x unknown\n",
642 bctx
->bvci
, pdu_type
);
643 rc
= bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC
, NULL
, msg
);
649 return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE
, NULL
, msg
);
652 /* We expect msgb_bssgph() to point to the BSSGP header */
653 int gprs_bssgp_rcvmsg(struct msgb
*msg
)
655 struct bssgp_normal_hdr
*bgph
=
656 (struct bssgp_normal_hdr
*) msgb_bssgph(msg
);
657 struct bssgp_ud_hdr
*budh
= (struct bssgp_ud_hdr
*) msgb_bssgph(msg
);
658 struct tlv_parsed tp
;
659 struct bssgp_bvc_ctx
*bctx
;
660 uint8_t pdu_type
= bgph
->pdu_type
;
661 uint16_t ns_bvci
= msgb_bvci(msg
);
665 /* Identifiers from DOWN: NSEI, BVCI (both in msg->cb) */
667 /* UNITDATA BSSGP headers have TLLI in front */
668 if (pdu_type
!= BSSGP_PDUT_UL_UNITDATA
&&
669 pdu_type
!= BSSGP_PDUT_DL_UNITDATA
) {
670 data_len
= msgb_bssgp_len(msg
) - sizeof(*bgph
);
671 rc
= bssgp_tlv_parse(&tp
, bgph
->data
, data_len
);
673 data_len
= msgb_bssgp_len(msg
) - sizeof(*budh
);
674 rc
= bssgp_tlv_parse(&tp
, budh
->data
, data_len
);
677 /* look-up or create the BTS context for this BVC */
678 bctx
= btsctx_by_bvci_nsei(ns_bvci
, msgb_nsei(msg
));
679 /* Only a RESET PDU can create a new BVC context */
680 if (!bctx
&& pdu_type
!= BSSGP_PDUT_BVC_RESET
) {
681 LOGP(DBSSGP
, LOGL_NOTICE
, "NSEI=%u/BVCI=%u Rejecting PDU "
682 "type %u for unknown BVCI\n", msgb_nsei(msg
), ns_bvci
,
684 return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI
, NULL
, msg
);
688 log_set_context(BSC_CTX_BVC
, bctx
);
689 rate_ctr_inc(&bctx
->ctrg
->ctr
[BSSGP_CTR_PKTS_IN
]);
690 rate_ctr_add(&bctx
->ctrg
->ctr
[BSSGP_CTR_BYTES_IN
],
691 msgb_bssgp_len(msg
));
694 if (ns_bvci
== BVCI_SIGNALLING
)
695 rc
= gprs_bssgp_rx_sign(msg
, &tp
, bctx
);
696 else if (ns_bvci
== BVCI_PTM
)
697 rc
= bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT
, NULL
, msg
);
699 rc
= gprs_bssgp_rx_ptp(msg
, &tp
, bctx
);
704 /* Entry function from upper level (LLC), asking us to transmit a BSSGP PDU
705 * to a remote MS (identified by TLLI) at a BTS identified by its BVCI and NSEI */
706 int gprs_bssgp_tx_dl_ud(struct msgb
*msg
, struct sgsn_mm_ctx
*mmctx
)
708 struct bssgp_bvc_ctx
*bctx
;
709 struct bssgp_ud_hdr
*budh
;
710 uint8_t llc_pdu_tlv_hdr_len
= 2;
711 uint8_t *llc_pdu_tlv
, *qos_profile
;
712 uint16_t pdu_lifetime
= 1000; /* centi-seconds */
713 uint8_t qos_profile_default
[3] = { 0x00, 0x00, 0x20 };
714 uint16_t msg_len
= msg
->len
;
715 uint16_t bvci
= msgb_bvci(msg
);
716 uint16_t nsei
= msgb_nsei(msg
);
719 /* Identifiers from UP: TLLI, BVCI, NSEI (all in msgb->cb) */
720 if (bvci
<= BVCI_PTM
) {
721 LOGP(DBSSGP
, LOGL_ERROR
, "Cannot send DL-UD to BVCI %u\n",
726 bctx
= btsctx_by_bvci_nsei(bvci
, nsei
);
728 /* FIXME: don't simply create missing context, but reject message */
729 bctx
= btsctx_alloc(bvci
, nsei
);
732 if (msg
->len
> TVLV_MAX_ONEBYTE
)
733 llc_pdu_tlv_hdr_len
+= 1;
735 /* prepend the tag and length of the LLC-PDU TLV */
736 llc_pdu_tlv
= msgb_push(msg
, llc_pdu_tlv_hdr_len
);
737 llc_pdu_tlv
[0] = BSSGP_IE_LLC_PDU
;
738 if (llc_pdu_tlv_hdr_len
> 2) {
739 llc_pdu_tlv
[1] = msg_len
>> 8;
740 llc_pdu_tlv
[2] = msg_len
& 0xff;
742 llc_pdu_tlv
[1] = msg_len
& 0x7f;
743 llc_pdu_tlv
[1] |= 0x80;
746 /* FIXME: optional elements: Alignment, UTRAN CCO, LSA, PFI */
749 /* Old TLLI to help BSS map from old->new */
752 msgb_tvlv_push(msg
, BSSGP_IE_TLLI
, 4, htonl(*tlli_old
));
756 if (strlen(mmctx
->imsi
)) {
758 int imsi_len
= gsm48_generate_mid_from_imsi(mi
, mmctx
->imsi
);
760 msgb_tvlv_push(msg
, BSSGP_IE_IMSI
,
765 drx_params
= htons(mmctx
->drx_parms
);
766 msgb_tvlv_push(msg
, BSSGP_IE_DRX_PARAMS
, 2,
767 (uint8_t *) &drx_params
);
769 /* FIXME: Priority */
771 /* MS Radio Access Capability */
772 if (mmctx
->ms_radio_access_capa
.len
)
773 msgb_tvlv_push(msg
, BSSGP_IE_MS_RADIO_ACCESS_CAP
,
774 mmctx
->ms_radio_access_capa
.len
,
775 mmctx
->ms_radio_access_capa
.buf
);
778 /* prepend the pdu lifetime */
779 pdu_lifetime
= htons(pdu_lifetime
);
780 msgb_tvlv_push(msg
, BSSGP_IE_PDU_LIFETIME
, 2, (uint8_t *)&pdu_lifetime
);
782 /* prepend the QoS profile, TLLI and pdu type */
783 budh
= (struct bssgp_ud_hdr
*) msgb_push(msg
, sizeof(*budh
));
784 memcpy(budh
->qos_profile
, qos_profile_default
, sizeof(qos_profile_default
));
785 budh
->tlli
= htonl(msgb_tlli(msg
));
786 budh
->pdu_type
= BSSGP_PDUT_DL_UNITDATA
;
788 rate_ctr_inc(&bctx
->ctrg
->ctr
[BSSGP_CTR_PKTS_OUT
]);
789 rate_ctr_add(&bctx
->ctrg
->ctr
[BSSGP_CTR_BYTES_OUT
], msg
->len
);
791 /* Identifiers down: BVCI, NSEI (in msgb->cb) */
793 return gprs_ns_sendmsg(bssgp_nsi
, msg
);
796 /* Send a single GMM-PAGING.req to a given NSEI/NS-BVCI */
797 int gprs_bssgp_tx_paging(uint16_t nsei
, uint16_t ns_bvci
,
798 struct bssgp_paging_info
*pinfo
)
800 struct msgb
*msg
= bssgp_msgb_alloc();
801 struct bssgp_normal_hdr
*bgph
=
802 (struct bssgp_normal_hdr
*) msgb_put(msg
, sizeof(*bgph
));
803 uint16_t drx_params
= htons(pinfo
->drx_params
);
805 int imsi_len
= gsm48_generate_mid_from_imsi(mi
, pinfo
->imsi
);
811 msgb_nsei(msg
) = nsei
;
812 msgb_bvci(msg
) = ns_bvci
;
814 if (pinfo
->mode
== BSSGP_PAGING_PS
)
815 bgph
->pdu_type
= BSSGP_PDUT_PAGING_PS
;
817 bgph
->pdu_type
= BSSGP_PDUT_PAGING_CS
;
819 msgb_tvlv_put(msg
, BSSGP_IE_IMSI
, imsi_len
-2, mi
+2);
821 msgb_tvlv_put(msg
, BSSGP_IE_DRX_PARAMS
, 2,
822 (uint8_t *) &drx_params
);
824 switch (pinfo
->scope
) {
825 case BSSGP_PAGING_BSS_AREA
:
828 msgb_tvlv_put(msg
, BSSGP_IE_BSS_AREA_ID
, 1, &null
);
831 case BSSGP_PAGING_LOCATION_AREA
:
832 gsm48_construct_ra(ra
, &pinfo
->raid
);
833 msgb_tvlv_put(msg
, BSSGP_IE_LOCATION_AREA
, 4, ra
);
835 case BSSGP_PAGING_ROUTEING_AREA
:
836 gsm48_construct_ra(ra
, &pinfo
->raid
);
837 msgb_tvlv_put(msg
, BSSGP_IE_ROUTEING_AREA
, 6, ra
);
839 case BSSGP_PAGING_BVCI
:
841 uint16_t bvci
= htons(pinfo
->bvci
);
842 msgb_tvlv_put(msg
, BSSGP_IE_BVCI
, 2, (uint8_t *)&bvci
);
846 /* QoS profile mandatory for PS */
847 if (pinfo
->mode
== BSSGP_PAGING_PS
)
848 msgb_tvlv_put(msg
, BSSGP_IE_QOS_PROFILE
, 3, pinfo
->qos
);
850 /* Optional (P-)TMSI */
852 uint32_t ptmsi
= htonl(*pinfo
->ptmsi
);
853 msgb_tvlv_put(msg
, BSSGP_IE_TMSI
, 4, (uint8_t *) &ptmsi
);
856 return gprs_ns_sendmsg(bssgp_nsi
, msg
);