Failed to activate PDN for CID

I'm having trouble activating a PDN on a running/connected device. Here's the code:

int set_apn(char *apn)
{
    int err = 0;
    int esm = 0;
    char current[128];

    /* Get the current default */
    err = pdn_default_apn_get(current, sizeof(current));
    if (err)
    {
        LOG_ERR("pdn_default_apn_get error: %i", err);
        return err;
    }

    /* Don't do anything if APN is the same */
    if (strcmp(current, apn) == 0)
    {
        LOG_INF("No update neded. APN matches: %s", log_strdup(apn));
        return 0;
    }

    /* Create a PDP context and assign an event handler to receive events */
    err = pdn_ctx_create(&cid, pdn_event_handler);
    if (err)
    {
        LOG_ERR("pdn_ctx_create() failed, err %i", err);
        pdn_ctx_destroy(cid);
        return err;
    }

    LOG_INF("Created new PDP context %d", cid);

    /* Configure a PDP context with APN and Family */
    err = pdn_ctx_configure(cid, apn, PDN_FAM_IPV4V6, NULL);
    if (err)
    {
        LOG_ERR("pdn_ctx_configure() failed, err %i", err);
        pdn_ctx_destroy(cid);
        return err;
    }

    LOG_INF("PDP context %i configured: APN %s", cid, log_strdup(apn));

    /* Activate a PDN connection */
    err = pdn_activate(cid, &esm, NULL);
    if (err < 0)
    {
        LOG_ERR("pdn_activate() failed, err %i esm %i",
                err, esm);
        pdn_ctx_destroy(cid);
        return err;
    }

    return 0;
}

Seems like I'm missing something here. pdn_init does get called on system setup. (using CONFIG_PDN_SYS_INIT=y)

[00:00:25.517,486] <inf> main: Evt: APP_EVENT_APN_UPDATE
[00:00:25.517,517] <inf> main: ------------------- POST status 43
[00:00:25.517,547] <inf> main: Set apn to: Att (len: 3)
[00:00:25.531,402] <inf> main: Created new PDP context 1
[00:00:25.531,890] <inf> main: PDP context 1 configured: APN Att
[00:00:25.772,003] <wrn> pdn: Failed to activate PDN for CID 1, err 65536
[00:00:26.772,125] <err> main: pdn_activate() failed, err -8 esm 0 <unknown>

Parents Reply
  • Hi,

     

    Jared said:
    The device does obtain a default beforehand. Is that the problem?

    What is the output if you run AT+CGDCONT? at your end? If you run the "pdn" sample, are you able to successfully set the pdn then?

     

    Jared said:
    CONFIG_PDN_SYS_INIT was set to 'y' by default.

    This means that NRF_MODEM_LIB is sys-init'ed prior to entering main, correct?

    Can you try to set this to 'n' and run pdn_init() in your application?

     

    Kind regards,

    Håkon

Children
  • Hi  

    This means that NRF_MODEM_LIB is sys-init'ed prior to entering main, correct?

    Can you try to set this to 'n' and run pdn_init() in your application?

    I tried this exact thing with the same result.

    As far as I can tell, CONFIG_PDN_SYS_INIT is getting selected because 

    CONFIG_NRF_MODEM_LIB_SYS_INIT is also selected/enabled.

    Here's the response after my attempt of running AT+CGDCONT?

    [00:00:37.759,399] <inf> main: Set apn to: Att (len: 3)
    [00:00:37.761,291] <inf> main: Created new PDP context 1
    [00:00:37.761,779] <inf> main: PDP context 1 configured: APN Att
    [00:00:39.250,213] <wrn> pdn: Failed to activate PDN for CID 1, err 65536
    [00:00:40.250,335] <err> main: pdn_activate() failed, err -8 esm 0
    [00:00:40.251,373] <inf> main: +CGDCONT: 0,"IP","hologram","10.95.240.159",0,0
    OK

    We are using NCS 1.9.1 with MFW 1.3.1. Are there any caveats we need to be aware of?

    If you run the "pdn" sample, are you able to successfully set the pdn then?

    Here is the sample. This just re-programs the same APN and works.

    [00:00:00.214,965] <inf> main: PDN sample started
    [00:00:02.750,976] <inf> main: Event: PDP context 0 activated
    [00:00:02.753,570] <inf> main: Default APN is hologram
    [00:00:02.753,967] <inf> main: Created new PDP context 1
    [00:00:02.754,486] <inf> main: PDP context 1 configured: APN hologram, Family IPV4V6
    [00:00:02.755,218] <inf> main: Event: PDP context 1 activated
    [00:00:03.764,312] <inf> main: PDP Context 0, PDN ID 0
    [00:00:03.764,801] <inf> main: PDP Context 1, PDN ID 0
    [00:00:03.859,497] <inf> main: Event: PDP context 0 deactivated
    [00:00:03.860,046] <inf> main: Event: PDP context 1 deactivated
    [00:00:05.382,812] <inf> main: Bye

    This is what happens when a different one is attempted:

    [00:00:00.215,026] <inf> main: PDN sample started
    [00:00:02.356,994] <inf> main: Event: PDP context 0 activated
    [00:00:02.359,130] <inf> main: Default APN is hologram
    [00:00:02.359,527] <inf> main: Created new PDP context 1
    [00:00:02.360,046] <inf> main: PDP context 1 configured: APN hologram, Family IPV4V6
    [00:00:02.524,841] <inf> main: Event: PDP context 1, Requested service option not subscribed
    [00:00:02.524,902] <wrn> pdn: Failed to activate PDN for CID 1, err 65536
    [00:00:02.524,932] <inf> main: pdn_activate() failed, err -8 esm 33 Requested service option not subscribed

  • Hi Jared,

     

    Jared said:
    We are using NCS 1.9.1 with MFW 1.3.1. Are there any caveats we need to be aware of?

    No, not that I'm aware of.

    Effectively, you're calling "AT+CGACT=1,1" and this is failing.

    What is happening on your end is that the activation returns "ERROR" string back, ie. value 0x10000:

    https://github.com/nrfconnect/sdk-nrfxlib/blob/v2.1.1/nrf_modem/include/nrf_modem_at.h#L185

     

    Since you're using PDP context 1, this config should not be a problem for you, as it is defaulted to '1': https://github.com/nrfconnect/sdk-nrf/blob/v1.9.1/lib/pdn/Kconfig#L13-L19

    Jared said:
    This is what happens when a different one is attempted

    This gives a ESM cause code returned from the network, which is expected if the APN given is not valid. Effectively, all the AT commands were successful here, although the result was negative.

     

    Could you share details on how to recreate the scenario so I can try at my end?

     

    Kind regards,

    Håkon

  • Hi  

    I went ahead and researched the error from the PDN sample since my code was not producing something useful. 

    This was the error line:

    pdn_activate() failed, err -8 esm 33 Requested service option not subscribed

    I believe it comes down to the SIM not being registered for the APN that is being requested. It gets rejected during the activation phase. I was assured that it would work but I think my customer needs to go back to their provider to figure out a solution.

    Let me know if you agree on this point.

    I've included the modified PDN sample where I try to activate "Att". It's not supported on this SIM so it fails whereas if I simply activate the default it works a-ok.

    /*
     * Copyright (c) 2021 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <stdio.h>
    #include <stdint.h>
    #include <zephyr.h>
    #include <modem/pdn.h>
    #include <modem/lte_lc.h>
    #include <nrf_modem_at.h>
    
    #include <logging/log.h>
    LOG_MODULE_REGISTER(main);
    
    extern const char *esm_strerr(int reason);
    
    static const char *const fam_str[] = {
        [PDN_FAM_IPV4V6] = "IPV4V6",
        [PDN_FAM_IPV6] = "IPV6",
        [PDN_FAM_IPV4] = "IPV4",
    };
    
    static const char *const event_str[] = {
        [PDN_EVENT_CNEC_ESM] = "ESM",
        [PDN_EVENT_ACTIVATED] = "activated",
        [PDN_EVENT_DEACTIVATED] = "deactivated",
        [PDN_EVENT_IPV6_UP] = "IPv6 up",
        [PDN_EVENT_IPV6_DOWN] = "IPv6 down",
    };
    
    void pdn_event_handler(uint8_t cid, enum pdn_event event, int reason)
    {
        switch (event)
        {
        case PDN_EVENT_CNEC_ESM:
            LOG_INF("Event: PDP context %d, %s", cid, log_strdup(esm_strerr(reason)));
            break;
        default:
            LOG_INF("Event: PDP context %d %s", cid, log_strdup(event_str[event]));
            break;
        }
    }
    
    void main(void)
    {
        int err;
        int esm;
        uint8_t cid;
    
        char apn[32];
    
        LOG_INF("PDN sample started");
    
        /* Register to the necessary packet domain AT notifications */
        err = nrf_modem_at_printf("AT+CNEC=16");
        if (err)
        {
            LOG_INF("AT+CNEC=16 failed, err %d", err);
            return;
        }
    
        err = nrf_modem_at_printf("AT+CGEREP=1");
        if (err)
        {
            LOG_INF("AT+CGEREP=1 failed, err %d", err);
            return;
        }
    
        err = pdn_init();
        if (err)
        {
            return;
        }
    
        /* Setup a callback for the default PDP context (zero).
         * Do this before switching to function mode 1 (CFUN=1)
         * to receive the first activation event.
         */
        err = pdn_default_callback_set(pdn_event_handler);
        if (err)
        {
            LOG_INF("pdn_default_callback_set() failed, err %d", err);
            return;
        }
    
        err = lte_lc_init_and_connect();
        if (err)
        {
            return;
        }
    
        err = pdn_default_apn_get(apn, sizeof(apn));
        if (err)
        {
            LOG_INF("pdn_default_apn_get() failed, err %d", err);
            return;
        }
    
        LOG_INF("Default APN is %s", log_strdup(apn));
    
        /* Create a PDP context and assign an event handler to receive events */
        err = pdn_ctx_create(&cid, pdn_event_handler);
        if (err)
        {
            LOG_INF("pdn_ctx_create() failed, err %d", err);
            return;
        }
    
        LOG_INF("Created new PDP context %d", cid);
    
        /* Configure a PDP context with APN and Family */
        err = pdn_ctx_configure(cid, "Att", PDN_FAM_IPV4V6, NULL);
        if (err)
        {
            LOG_INF("pdn_ctx_configure() failed, err %d", err);
            return;
        }
    
        LOG_INF("PDP context %d configured: APN %s, Family %s",
               cid, log_strdup(apn), log_strdup(fam_str[PDN_FAM_IPV4V6]));
    
        /* Activate a PDN connection */
        err = pdn_activate(cid, &esm, NULL);
        if (err)
        {
            LOG_INF("pdn_activate() failed, err %d esm %d %s",
                   err, esm, log_strdup(esm_strerr(esm)));
            return;
        }
    
        LOG_INF("PDP Context %d, PDN ID %d", 0, pdn_id_get(0));
        LOG_INF("PDP Context %d, PDN ID %d", cid, pdn_id_get(cid));
    
        lte_lc_power_off();
        LOG_INF("Bye");
    }
    

  • Hi,

    Jared said:
    Let me know if you agree on this point.

    Yes, I agree with your findings. 

    Jared said:
    This was the error line:

    Ah, that makes more sense.. The PDN sample automatically subscribes to error codes in main, and this was moved to the library itself after v1.9.x was released, via this PR: https://github.com/nrfconnect/sdk-nrf/commit/d7d1e73d34578228a825539e576efc89ef988e0a

     

    Effectively, if your app is not subscribing explicitly to the notifications (CNEC=16), then you'll not get the ESM cause code returned back to the application space.

     

    Kind regards,

    Håkon

Related