Skip to content

Commit ea21427

Browse files
trantanenSeppoTakalo
authored andcommitted
applications: serial_lte_modem: Add PPP PDN selection
Add support for selecting PDN used with PPP connection into #XPPP command. E.g., AT#XPPP=1,1 for enabling PPP for PDP context with CID 1. Jira: LRCS-149 Signed-off-by: Tommi Rantanen <[email protected]>
1 parent bcbba84 commit ea21427

File tree

3 files changed

+118
-49
lines changed

3 files changed

+118
-49
lines changed

applications/serial_lte_modem/doc/PPP_AT_commands.rst

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,53 +27,62 @@ Control PPP #XPPP
2727
Set command
2828
-----------
2929

30-
The set command allows you to start and stop PPP.
30+
The set command allows you to start and stop PPP, and optionally define the PDN connection used for PPP.
3131

3232
.. note::
3333

34-
PPP is automatically started and stopped by SLM when the default PDN connection is established and lost, respectively.
34+
PPP is automatically started and stopped by SLM when the PDN connection requested for PPP
35+
is established and lost, respectively.
3536
This happens even if PPP has previously been stopped or started with this command.
3637

3738
Syntax
3839
~~~~~~
3940

4041
::
4142

42-
#XPPP=<op>
43+
#XPPP=<op>[,<cid>]
4344

4445
* The ``<op>`` parameter can be the following:
4546

4647
* ``0`` - Stop PPP.
4748
* ``1`` - Start PPP.
4849

50+
* The ``<cid>`` parameter is an integer indicating the PDN connection to be used for PPP.
51+
It represents ``cid`` in the ``+CGDCONT`` command.
52+
Its default value is ``0``, which represents the default PDN connection.
53+
4954
Unsolicited notification
5055
~~~~~~~~~~~~~~~~~~~~~~~~
5156

5257
.. slm_ppp_status_notif_start
5358
5459
::
5560

56-
#XPPP: <running>,<peer_connected>
61+
#XPPP: <running>,<peer_connected>,<cid>
5762

5863
* The ``<running>`` parameter is an integer that indicates whether PPP is running.
5964
It is ``1`` for running or ``0`` for stopped.
6065

6166
* The ``<peer_connected>`` parameter is an integer that indicates whether a peer is connected to PPP.
6267
It is ``1`` for connected or ``0`` for not connected.
6368

69+
* The ``<cid>`` parameter is an integer that indicates the PDN connection used for PPP.
70+
6471
.. slm_ppp_status_notif_end
6572
66-
Example
67-
-------
73+
Examples
74+
--------
75+
76+
PPP with default PDN connection:
6877

6978
::
7079

7180
AT+CFUN=1
7281

7382
OK
7483

75-
// PPP is automatically started when the modem is registered to the network.
76-
#XPPP: 1,0
84+
// PPP is automatically started when the default PDN is activated.
85+
#XPPP: 1,0,0
7786

7887
// Stop PPP.
7988
AT#XPPP=0
@@ -87,25 +96,54 @@ Example
8796

8897
OK
8998

90-
#XPPP: 1,0
99+
#XPPP: 1,0,0
91100

92101
// Have the peer connect to SLM's PPP.
93-
#XPPP: 1,1
102+
#XPPP: 1,1,0
94103

95104
// Peer disconnects.
96-
#XPPP: 1,0
105+
#XPPP: 1,0,0
97106

98107
// SLM restarts PPP automatically when peer disconnects.
99-
#XPPP: 0,0
108+
#XPPP: 0,0,0
100109

101-
#XPPP: 1,0
110+
#XPPP: 1,0,0
102111

103112
AT+CFUN=4
104113

105114
OK
106115

107116
#XPPP: 0,0
108117

118+
PPP with non-default PDN connection:
119+
120+
::
121+
122+
// Exemplary PDN connection creation.
123+
// Note: APN depends on operator and additional APNs may not be supported by the operator.
124+
AT+CGDCONT=1,"IP","internet2"
125+
126+
OK
127+
128+
// Start PPP with the created PDN connection. This must be before AT+CFUN=1 command or
129+
// otherwise PPP will be started for the default PDN connection.
130+
AT#XPPP=1,1
131+
132+
OK
133+
134+
AT+CFUN=1
135+
136+
OK
137+
138+
// Activate the created PDN connection.
139+
AT+CGACT=1,1
140+
141+
// PPP is automatically started when the PDN connection set for PPP has been activated.
142+
#XPPP: 1,0,1
143+
144+
// Have the peer connect to SLM's PPP.
145+
#XPPP: 1,1,1
146+
109147
Read command
110148
------------
111149

@@ -128,20 +166,15 @@ Response syntax
128166
Testing on Linux
129167
================
130168

131-
You can test SLM's PPP on Linux by using the ``pppd`` command, though SLM must be compiled without CMUX because there is no widely available utility that allows multiplexing a device file on Linux.
132-
133-
.. note::
134-
135-
If you have a utility that allows multiplexing a device file on Linux, you can use SLM's PPP with the ``pppd`` command through CMUX.
136-
To do this, you must first set up the CMUX link.
137-
Then, make sure to replace the device file argument in the ``pppd`` command with that of SLM's PPP channel, which will have been created by the CMUX utility.
138-
See :ref:`SLM_AT_CMUX` for more information on SLM's CMUX.
169+
You can test SLM's PPP on Linux by using the ``pppd`` command.
170+
This section describes a configuration without CMUX.
171+
If you are using CMUX, see :ref:`slm_as_linux_modem` for more information on setting it up.
139172

140173
For the process described here, SLM's UARTs must be connected to the Linux host.
141174

142175
1. Get PPP running on SLM.
143176
To do this, start SLM and issue an ``AT+CFUN=1`` command.
144-
#. Wait for ``#XPPP: 1,0``, which is sent when the network registration succeeds and PPP has started successfully.
177+
#. Wait for ``#XPPP: 1,0,0``, which is sent when the network registration succeeds and PPP has started successfully with the default PDN connection.
145178
#. Run the following command on the Linux host:
146179

147180
.. code-block:: console

applications/serial_lte_modem/src/slm_ppp.c

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ MODEM_PPP_DEFINE(ppp_module, NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
8181

8282
static struct modem_pipe *ppp_pipe;
8383

84-
/* We use only the default PDP context. */
85-
enum { PDP_CID = 0 };
84+
/* Default PPP PDN is the default PDP context (CID 0). */
85+
static unsigned int ppp_pdn_cid;
8686

8787
enum {
8888
ZEPHYR_FD_IDX, /* Raw Zephyr socket to pass data to/from the PPP link. */
@@ -123,6 +123,18 @@ static bool open_ppp_sockets(void)
123123
return false;
124124
}
125125

126+
/* Bind PPP to PDN */
127+
ret = zsock_setsockopt(
128+
ppp_fds[MODEM_FD_IDX],
129+
SOL_SOCKET, SO_BINDTOPDN,
130+
&ppp_pdn_cid, sizeof(int));
131+
if (ret == 0) {
132+
LOG_INF("PPP socket bound to PDN %d", ppp_pdn_cid);
133+
} else {
134+
LOG_ERR("Failed to bind PPP to PDN %d (%d)", ppp_pdn_cid, -errno);
135+
return false;
136+
}
137+
126138
return true;
127139
}
128140

@@ -147,7 +159,7 @@ static bool configure_ppp_link_ip_addresses(struct ppp_context *ctx)
147159
char addr4[INET_ADDRSTRLEN];
148160
char addr6[INET6_ADDRSTRLEN];
149161

150-
util_get_ip_addr(PDP_CID, addr4, addr6);
162+
util_get_ip_addr(ppp_pdn_cid, addr4, addr6);
151163

152164
if (*addr4) {
153165
if (zsock_inet_pton(AF_INET, addr4, &ctx->ipcp.my_options.address) != 1) {
@@ -190,7 +202,7 @@ static bool ppp_is_running(void)
190202

191203
static void send_status_notification(void)
192204
{
193-
rsp_send("\r\n#XPPP: %u,%u\r\n", ppp_is_running(), ppp_peer_connected);
205+
rsp_send("\r\n#XPPP: %u,%u,%u\r\n", ppp_is_running(), ppp_peer_connected, ppp_pdn_cid);
194206
}
195207

196208
static int ppp_start_failure(int ret)
@@ -204,7 +216,7 @@ static unsigned int ppp_retrieve_mtu(void)
204216
{
205217
struct pdn_dynamic_info populated_info = { 0 };
206218

207-
if (!pdn_dynamic_info_get(PDP_CID, &populated_info)) {
219+
if (!pdn_dynamic_info_get(ppp_pdn_cid, &populated_info)) {
208220
if (populated_info.ipv6_mtu) {
209221
/* Set the PPP MTU to that of the LTE link. */
210222
/* IPv6's MTU has more priority on dual-stack.
@@ -339,24 +351,6 @@ static void ppp_stop(void)
339351
}
340352
}
341353

342-
/* Automatically starts/stops PPP when the default PDN connection goes up/down. */
343-
static void pdp_ctx_event_handler(uint8_t cid, enum pdn_event event, int reason)
344-
{
345-
switch (event) {
346-
case PDN_EVENT_ACTIVATED:
347-
LOG_INF("Connection up. Starting PPP.");
348-
k_work_submit_to_queue(&slm_work_q, &ppp_restart_work.work);
349-
break;
350-
case PDN_EVENT_DEACTIVATED:
351-
LOG_DBG("Connection down.");
352-
ppp_stop();
353-
break;
354-
default:
355-
LOG_DBG("Default PDN connection event %d received.", event);
356-
break;
357-
}
358-
}
359-
360354
/* We need to receive CGEV notifications at all times.
361355
* CGEREP AT commands are intercepted to prevent the user
362356
* from unsubcribing us and make that behavior invisible.
@@ -415,6 +409,39 @@ static void subscribe_cgev_notifications(void)
415409
}
416410
}
417411

412+
AT_MONITOR(slm_ppp_on_cgev, "CGEV", at_notif_on_cgev);
413+
414+
static void at_notif_on_cgev(const char *notify)
415+
{
416+
char *str;
417+
char *endptr;
418+
uint8_t cid;
419+
char cgev_pdn_act[] = "+CGEV: ME PDN ACT";
420+
421+
/* +2 for space and a number */
422+
if (strlen(cgev_pdn_act) + 2 > strlen(notify)) {
423+
/* Ignore notifications that are not long enough to be what we are interested in */
424+
return;
425+
}
426+
427+
/* Only activation of PPP PDN is monitored here.
428+
* Deactivation of PPP PDN or detach from network will cause PPP socket to get closed
429+
* from where stopping of PPP is triggered.
430+
*/
431+
str = strstr(notify, cgev_pdn_act);
432+
if (str != NULL) {
433+
str += strlen(cgev_pdn_act);
434+
if (*str == ' ') {
435+
str++;
436+
cid = (uint8_t)strtoul(str, &endptr, 10);
437+
if (endptr != str && cid == ppp_pdn_cid) {
438+
LOG_INF("PPP PDN (%d) activated. Starting PPP.", ppp_pdn_cid);
439+
k_work_submit_to_queue(&slm_work_q, &ppp_restart_work.work);
440+
}
441+
}
442+
}
443+
}
444+
418445
/* Notification subscriptions are reset on CFUN=0.
419446
* We intercept CFUN set commands to automatically subscribe.
420447
*/
@@ -523,8 +550,6 @@ int slm_ppp_init(void)
523550

524551
net_if_flag_set(ppp_iface, NET_IF_POINTOPOINT);
525552

526-
pdn_default_ctx_cb_reg(pdp_ctx_event_handler);
527-
528553
{
529554
static struct net_mgmt_event_callback ppp_net_mgmt_event_cb;
530555

@@ -553,7 +578,7 @@ static int handle_at_ppp(enum at_parser_cmd_type cmd_type, struct at_parser *par
553578
send_status_notification();
554579
return 0;
555580
}
556-
if (cmd_type != AT_PARSER_CMD_TYPE_SET || param_count != 2) {
581+
if (cmd_type != AT_PARSER_CMD_TYPE_SET || param_count < 2 || param_count > 3) {
557582
return -EINVAL;
558583
}
559584

@@ -564,9 +589,16 @@ static int handle_at_ppp(enum at_parser_cmd_type cmd_type, struct at_parser *par
564589
return -EINVAL;
565590
}
566591

592+
if (op == OP_STOP && param_count != 2) {
593+
return -EINVAL;
594+
}
595+
567596
/* Send "OK" first in case stopping PPP results in the CMUX AT channel switching. */
568597
rsp_send_ok();
569598
if (op == OP_START) {
599+
ppp_pdn_cid = 0;
600+
/* Store PPP PDN if given */
601+
at_parser_num_get(parser, 2, &ppp_pdn_cid);
570602
k_work_submit_to_queue(&slm_work_q, &ppp_start_work.work);
571603
} else {
572604
k_work_submit_to_queue(&slm_work_q, &ppp_stop_work.work);
@@ -607,6 +639,7 @@ static void ppp_data_passing_thread(void*, void*, void*)
607639
LOG_WRN("Unexpected event 0x%x on %s socket.",
608640
revents, ppp_socket_names[src]);
609641
}
642+
LOG_DBG("Socket closed or connection down. Stopping PPP.");
610643
ppp_stop();
611644
return;
612645
}

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,10 @@ nRF Machine Learning (Edge Impulse)
221221
Serial LTE modem
222222
----------------
223223

224-
|no_changes_yet_note|
224+
* Updated:
225+
226+
* The ``AT#XPPP`` command to support the CID parameter to specify the PDN connection used for PPP.
227+
* The ``#XPPP`` notification to include the CID of the PDN connection used for PPP.
225228

226229
Thingy:53: Matter weather station
227230
---------------------------------

0 commit comments

Comments
 (0)