UE state leak: when HNB re-registers, discard previous UE state
User reports show leaked UE contexts over time, in a scenario where HNB regularly disconnect and reconnect. So far, when we receive a HNB REGISTER REQ, we log as "duplicated" and continue to use the hnb_context unchanged. But it seems obvious that a HNB that registers does not expect any UE state to remain. It will obviously not tear down UE contexts (HNBAP or RUA) that have been established before the HNB REGISTER REQUEST. These hence remain in osmo-hnbgw indefinitely. When receiving a HNB REGISTER REQUEST, release all its previous UE state. Allow the HNB to register with a clean slate. The aim is to alleviate the observed build-up of apparently orphaned UE contexts, in order to avoid gradual memory exhaustion. Related: SYS#6297 Change-Id: I7fa8a04cc3b2dfba263bda5b410961c77fbed332
This commit is contained in:
parent
a3c7f750a2
commit
8eefcbee92
|
@ -188,6 +188,7 @@ void ue_context_free(struct ue_context *ue);
|
||||||
|
|
||||||
struct hnb_context *hnb_context_alloc(struct hnb_gw *gw, struct osmo_stream_srv_link *link, int new_fd);
|
struct hnb_context *hnb_context_alloc(struct hnb_gw *gw, struct osmo_stream_srv_link *link, int new_fd);
|
||||||
void hnb_context_release(struct hnb_context *ctx);
|
void hnb_context_release(struct hnb_context *ctx);
|
||||||
|
void hnb_context_release_ue_state(struct hnb_context *ctx);
|
||||||
|
|
||||||
void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx);
|
void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx);
|
||||||
int hnbgw_vty_go_parent(struct vty *vty);
|
int hnbgw_vty_go_parent(struct vty *vty);
|
||||||
|
|
|
@ -395,15 +395,10 @@ const char *hnb_context_name(struct hnb_context *ctx)
|
||||||
return umts_cell_id_name(&ctx->id);
|
return umts_cell_id_name(&ctx->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hnb_context_release(struct hnb_context *ctx)
|
void hnb_context_release_ue_state(struct hnb_context *ctx)
|
||||||
{
|
{
|
||||||
struct hnbgw_context_map *map, *map2;
|
struct hnbgw_context_map *map, *map2;
|
||||||
|
|
||||||
LOGHNB(ctx, DMAIN, LOGL_INFO, "Releasing HNB context\n");
|
|
||||||
|
|
||||||
/* remove from the list of HNB contexts */
|
|
||||||
llist_del(&ctx->list);
|
|
||||||
|
|
||||||
/* deactivate all context maps */
|
/* deactivate all context maps */
|
||||||
llist_for_each_entry_safe(map, map2, &ctx->map_list, hnb_list) {
|
llist_for_each_entry_safe(map, map2, &ctx->map_list, hnb_list) {
|
||||||
/* remove it from list, as HNB context will soon be
|
/* remove it from list, as HNB context will soon be
|
||||||
|
@ -414,6 +409,16 @@ void hnb_context_release(struct hnb_context *ctx)
|
||||||
context_map_deactivate(map);
|
context_map_deactivate(map);
|
||||||
}
|
}
|
||||||
ue_context_free_by_hnb(ctx->gw, ctx);
|
ue_context_free_by_hnb(ctx->gw, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hnb_context_release(struct hnb_context *ctx)
|
||||||
|
{
|
||||||
|
LOGHNB(ctx, DMAIN, LOGL_INFO, "Releasing HNB context\n");
|
||||||
|
|
||||||
|
/* remove from the list of HNB contexts */
|
||||||
|
llist_del(&ctx->list);
|
||||||
|
|
||||||
|
hnb_context_release_ue_state(ctx);
|
||||||
|
|
||||||
if (ctx->conn) { /* we own a conn, we must free it: */
|
if (ctx->conn) { /* we own a conn, we must free it: */
|
||||||
LOGHNB(ctx, DMAIN, LOGL_INFO, "Closing HNB SCTP connection %s\n",
|
LOGHNB(ctx, DMAIN, LOGL_INFO, "Closing HNB SCTP connection %s\n",
|
||||||
|
|
|
@ -467,7 +467,15 @@ static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in)
|
||||||
|
|
||||||
LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "HNB-REGISTER-REQ %s MCC=%u,MNC=%u,LAC=%u,RAC=%u,SAC=%u,CID=%u from %s%s\n",
|
LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "HNB-REGISTER-REQ %s MCC=%u,MNC=%u,LAC=%u,RAC=%u,SAC=%u,CID=%u from %s%s\n",
|
||||||
ctx->identity_info, ctx->id.mcc, ctx->id.mnc, ctx->id.lac, ctx->id.rac, ctx->id.sac, ctx->id.cid,
|
ctx->identity_info, ctx->id.mcc, ctx->id.mnc, ctx->id.lac, ctx->id.rac, ctx->id.sac, ctx->id.cid,
|
||||||
name, ctx->hnb_registered ? " (duplicated)" : "");
|
name, ctx->hnb_registered ? " (re-connecting)" : "");
|
||||||
|
|
||||||
|
if (ctx->hnb_registered) {
|
||||||
|
/* The HNB is already registered, and we are seeing a new HNB Register Request. The HNB has restarted
|
||||||
|
* without us noticing. Clearly, the HNB does not expect any UE state to be active here, so discard any
|
||||||
|
* UE contexts and SCCP connections associated with this HNB. */
|
||||||
|
LOGHNB(ctx, DHNBAP, LOGL_NOTICE, "HNB reconnecting, discarding all previous UE state\n");
|
||||||
|
hnb_context_release_ue_state(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
ctx->hnb_registered = true;
|
ctx->hnb_registered = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue