pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ggsn/+/37691?usp=email )
Change subject: ggsn: kernel gtpu: Support updating pdp ctx remote IP address and TEID ......................................................................
ggsn: kernel gtpu: Support updating pdp ctx remote IP address and TEID
Whenever the SGSN sends the GGSN a UpdatePDPCtxReq, it may offer a new remote IP address or/and remote TEID, eg. because it wants to establish a Direct Tunnel and point the GTPU towards the RNC, or to point it back to itself. If the gtpu kernel is used, osmo-ggsn lacked updating the kernel with the new remote data. The gtp kernel module doesn't provide an efficient/explicit way to update a pdp context keeping the4 same local IP+TEID and changing only the remote remote IP+TEID, hence first destroy the pdp ctx in the gtp kernel module and then recreate it.
This fixes test GGSN_Tests_v4_only.TC_pdp4_act_update_teid in ttcn3-ggsn-test-kernel-net-next.
Related: OS#6523 Change-Id: I1fc48be5c0f177ccf6fbe97c003b4df44809c0fe --- M ggsn/ggsn.c 1 file changed, 37 insertions(+), 1 deletion(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c index e682a26..a6cfc58 100644 --- a/ggsn/ggsn.c +++ b/ggsn/ggsn.c @@ -582,6 +582,41 @@ return 0; }
+static int update_context_ind(struct pdp_t *pdp) +{ + char apn_name[256]; + struct gsn_t *gsn = pdp->gsn; + struct ggsn_ctx *ggsn = gsn->priv; + struct apn_ctx *apn; + bool apn_found = false; + int rc; + + if (!osmo_apn_to_str(apn_name, pdp->apn_use.v, pdp->apn_use.l)) { + LOGPPDP(LOGL_ERROR, pdp, "Unable to decode associated APN len=%d buf: %s\n", + pdp->apn_use.l, osmo_hexdump(pdp->apn_use.v, pdp->apn_use.l)); + return gtp_update_context_resp(ggsn->gsn, pdp, GTPCAUSE_MISSING_APN); + } + + llist_for_each_entry (apn, &ggsn->apn_list, list) { + if (strncmp(apn_name, apn->cfg.name, sizeof(apn_name)) != 0) + continue; + apn_found = true; + break; + } + if (!apn_found) { + LOGPPDP(LOGL_ERROR, pdp, "Unable to find associated APN %s\n", apn_name); + return gtp_update_context_resp(ggsn->gsn, pdp, GTPCAUSE_MISSING_APN); + } + + if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP) { + /* Update the kernel with the potentially new remote data IP address + TEID */ + gtp_kernel_tunnel_del(pdp, apn->tun.cfg.dev_name); + gtp_kernel_tunnel_add(pdp, apn->tun.cfg.dev_name); + } + rc = gtp_update_context_resp(ggsn->gsn, pdp, GTPCAUSE_ACC_REQ); + return rc; +} + /* Internet-originated IP packet, needs to be sent via GTP towards MS */ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) { @@ -848,8 +883,9 @@ OSMO_ASSERT(rc == 0);
gtp_set_cb_data_ind(ggsn->gsn, encaps_tun); - gtp_set_cb_delete_context(ggsn->gsn, delete_context); gtp_set_cb_create_context_ind(ggsn->gsn, create_context_ind); + gtp_set_cb_update_context_ind(ggsn->gsn, update_context_ind); + gtp_set_cb_delete_context(ggsn->gsn, delete_context); gtp_set_cb_conf(ggsn->gsn, cb_conf); gtp_set_cb_recovery3(ggsn->gsn, cb_recovery3);