第 2 章 - Azure RTOS NetX PPPoE 客户端的安装和使用

本章包含与安装、设置和使用 Azure RTOS NetX PPPoE 客户端组件相关的各种问题的说明。

产品分发

适用于 NetX 的 PPPoE 客户端可从 https://github.com/azure-rtos/netx 获得。 该包中包含以下文件:

  • nx_pppoe_client.h:适用于 NetX 的 PPPoE 客户端的头文件
  • nx_pppoe_client.c:适用于 NetX 的 PPPoE 客户端的 C 源文件
  • nx_pppoe_client.pdf:适用于 NetX 的 PPPoE 客户端的 PDF 说明
  • demo_netx_pppoe_client.c:NetX PPPoE 客户端演示

PPPoE 客户端安装

要使用适用于 NetX 的 PPPoE 客户端,应将前面提到的整个分发包复制到 NetX 所安装在的目录中。 例如,如果 NetX 安装在“\threadx\arm7\green”目录中,则应将 nx_pppoe_client.h 和 nx_pppoe_client.c 文件复制到该目录中。

使用 PPPoE 客户端

使用适用于 NetX 的 PPPoE 客户端非常简单。 总体上,应用程序代码必须先包含 tx_api.h 和 nx_api.h,然后包含 nx_pppoe_client.h,才能分别使用 ThreadX 和 NetX。 包含 nx_pppoe_client.h 之后,应用程序代码就可以进行本指南随后部分所述的 PPPoE 客户端函数调用。 应用程序还必须在生成过程中包含 nx_pppoe_client.c。 此文件必须采用与其他应用程序文件相同的方式来编译,并且其对象窗体必须与该应用程序的文件一起链接。 这就是使用 NetX PPPoE 客户端所需的一切。

小型示例系统

下面的示例演示如何使用 NetX PPPoE 客户端,如图 1.1 所述。 在此示例中,第 50 行引入 PPPoE 客户端包含文件 nx_pppoe_client.h。 接下来,在“thread_0_entry”中的第 238 行创建 PPPoE 客户端。 请注意,应该先创建 IP 实例,然后再创建 PPPoE 客户端。 在第 142-220 行,创建并初始化 IP 实例和 PPP 实例。 在之前的第 75 行,已将 PPPoE 客户端控制块“pppoe_client”定义为全局变量。 send 和 receive 函数在第 238 行进行设置。

通常,PPPoE 模块应与 PPP 模块配合使用。 在此示例中,第 49 行引入 PPP 客户端包含文件 nx_ppp.h。 接下来,在第 164 行创建 PPP 客户端。 第 172 行设置用于发送 PPP 数据包的函数。 第 179-190 行设置 IP 地址,并定义 pap 协议。 第 104-129 行设置 pap 协议的用户名和密码。

PPPoE 会话建立之后, 在第 264 行,应用程序可以调用 nx_pppoe_client_session_get,获取会话信息(服务器 MAC 地址和会话 id)。 在第 283 行,PPP 或应用程序可以调用 nx_pppoe_client_session_packet_send,发送 PPPoE 数据包。

当应用程序不再处理 PPP 流量时,应用程序可以调用 nx_pppoe_client_session_terminate 终止 PPPoE 会话。

请注意,在此示例中,PPPoE 客户端与普通 IP 堆栈同时运行,并共享一个以太网驱动程序。 在第 155 行,传递同一以太网驱动程序以创建普通 IP 实例,并在第 298 行传递该驱动程序以创建 PPPoE 客户端实例。

注意

将 NX_PHYSICAL_HEADER 重新定义为 24,确保有足够的空间可用于填充物理标头。 物理标头:14(以太网标头)+ 6(PPPoE 标头)+ 2(PPP 标头)+ 2(四字节对齐)。

  1 /**************************************************************************/
  2 /**************************************************************************/
  3 /**                                                                       */
  4 /** NetX PPPoE Client stack Component                                     */
  5 /**                                                                       */
  6 /**   This is a small demo of the high-performance NetX PPPoE Client      */
  7 /**   stack. This demo includes IP instance, PPPoE Client and PPP Client  */
  8 /**   stack. Create one IP instance includes two interfaces to support    */
  9 /**   for normal IP stack and PPPoE Client, PPPoE Client can use the      */
 10 /**   mutex of IP instance to send PPPoE message when share one Ethernet  */
 11 /**   driver. PPPoE Client work with normal IP instance at the same time. */
 12 /**                                                                       */
 13 /**   Note1: Substitute your Ethernet driver instead of                   */
 14 /**   _nx_ram_network_driver before run this demo                         */
 15 /**                                                                       */
 16 /**   Note2: Prerequisite for using PPPoE.                                */
 17 /**   Redefine NX_PHYSICAL_HEADER to 24 to ensure enough space for filling*/
 18 /**   in physical header. Physical header:14(Ethernet header)             */
 19 /**    + 6(PPPoE header) + 2(PPP header) + 2(four-byte aligment)          */
 20 /**                                                                       */
 21 /**************************************************************************/
 22 /**************************************************************************/
 23
 24
 25       /*****************************************************************/
 26       /*                          NetX Stack                           */
 27       /*****************************************************************/
 28
 29                                             /***************************/
 30                                             /*        PPP Client       */
 31                                             /***************************/
 32
 33                                             /***************************/
 34                                             /*       PPPoE Client      */
 35                                             /***************************/
 36       /***************************/         /***************************/
 37       /*    Normal Ethernet Type */         /*    PPPoE Ethernet Type  */
 38       /***************************/         /***************************/
 39       /***************************/         /***************************/
 40       /*       Interface 0       */         /*       Interface 1       */
 41       /***************************/         /***************************/
 42
 43       /*****************************************************************/
 44       /*                       Ethernet Dirver                         */
 45       /*****************************************************************/
 46
 47 #include   "tx_api.h"
 48 #include   "nx_api.h"
 49 #include   "nx_ppp.h"
 50 #include   "nx_pppoe_client.h"
 51
 52 /* Defined NX_PPP_PPPOE_ENABLE if use Express Logic's PPP, since PPP module has been modified
       to match PPPoE moduler under this definition.  */
 53 #ifdef NX_PPP_PPPOE_ENABLE
 54
 55 /* If the driver is not initialized in other module, define NX_PPPOE_CLIENT_INITIALIZE_DRIVER_ENABLE
       to initialize the driver in PPPoE module .
 56    In this demo, the driver has been initialized in IP module.  */
 57 #ifndef NX_PPPOE_CLIENT_INITIALIZE_DRIVER_ENABLE
 58
 59 /* Define the block size.  */
 60 #define     NX_PACKET_POOL_SIZE     ((1536 + sizeof(NX_PACKET)) * 30)
 61 #define     DEMO_STACK_SIZE         2048
 62 #define     PPPOE_THREAD_SIZE       2048
 63
 64 /* Define the ThreadX and NetX object control blocks...  */
 65 TX_THREAD               thread_0;
 66
 67 /* Define the packet pool and IP instance for normal IP instnace.  */
 68 NX_PACKET_POOL          pool_0;
 69 NX_IP                   ip_0;
 70
71 /* Define the PPP Client instance.  */
 72 NX_PPP                  ppp_client;
 73
 74 /* Define the PPPoE Client instance.  */
 75 NX_PPPOE_CLIENT         pppoe_client;
 76
 77 /* Define the counters.  */
 78 CHAR                    *pointer;
 79 ULONG                   error_counter;
 80
 81 /* Define thread prototypes.  */
 82 void    thread_0_entry(ULONG thread_input);
 83
 84 /***** Substitute your PPP driver entry function here *********/
 85 extern void    _nx_ppp_driver(NX_IP_DRIVER *driver_req_ptr);
 86
 87 /***** Substitute your Ethernet driver entry function here *********/
 88 extern void    _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
 89
 90 /* Define the porting layer function for Express Logic's PPP to simulate TTP's PPP.
 91    Functions to be provided by PPP for calling by the PPPoE Stack.  */
 92 void    ppp_client_packet_send(NX_PACKET *packet_ptr);
 93 void    pppoe_client_packet_receive(NX_PACKET *packet_ptr);
 94
 95 /* Define main entry point.  */
 96
 97 int main()
 98 {
 99
100     /* Enter the ThreadX kernel.  */
101     tx_kernel_enter();
102 }
103
104 UINT generate_login(CHAR *name, CHAR *password)
105 {
106
107     /* Make a name and password, called "myname" and "mypassword".  */
108     name[0] = 'm';
109     name[1] = 'y';
110     name[2] = 'n';
111     name[3] = 'a';
112     name[4] = 'm';
113     name[5] = 'e';
114     name[6] = (CHAR) 0;
115
116     password[0] = 'm';
117     password[1] = 'y';
118     password[2] = 'p';
119     password[3] = 'a';
120     password[4] = 's';
121     password[5] = 's';
122     password[6] = 'w';
123     password[7] = 'o';
124     password[8] = 'r';
125     password[9] = 'd';
126     password[10] = (CHAR) 0;
127
128     return(NX_SUCCESS);
129 }
130
131 /* Define what the initial system looks like.  */
132
133 void    tx_application_define(void *first_unused_memory)
134 {
135
136 UINT    status;
137
138     /* Setup the working pointer.  */
139     pointer =  (CHAR *) first_unused_memory;
140
141     /* Initialize the NetX system.  */
142     nx_system_initialize();
143
144     /* Create a packet pool for normal IP instance.  */
145     status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool",
146                                    (1536 + sizeof(NX_PACKET)),
147                                    pointer, NX_PACKET_POOL_SIZE);
148     pointer = pointer + NX_PACKET_POOL_SIZE;
149
150     /* Check for error.  */
151     if (status)
152         error_counter++;
153
154     /* Create an normal IP instance.  */
155     status = nx_ip_create(&ip_0, "NetX IP Instance", IP_ADDRESS(192, 168, 100, 44), 0xFFFFFF00UL,
156                           &pool_0, _nx_ram_network_driver, pointer, 2048, 1);
157     pointer = pointer + 2048;
158
159     /* Check for error.  */
160     if (status)
161         error_counter++;
162
163     /* Create the PPP instance.  */
164     status = nx_ppp_create(&ppp_client, "PPP Instance", &ip_0, pointer, 2048, 1,
165                            &pool_0, NX_NULL, NX_NULL); pointer = pointer + 2048;
166
167     /* Check for PPP create error.   */
168     if (status)
169         error_counter++;
170
171     /* Set the PPP packet send function.  */
172     status = nx_ppp_packet_send_set(&ppp_client, ppp_client_packet_send);
173
174     /* Check for PPP packet send function set error.   */
175     if (status)
176         error_counter++;
177
178     /* Define IP address. This PPP instance is effectively the client since it doesn't have
           any IP addresses. */
179     status = nx_ppp_ip_address_assign(&ppp_client, IP_ADDRESS(0, 0, 0, 0), IP_ADDRESS(0, 0, 0, 0));
180
181     /* Check for PPP IP address assign error.   */
182     if (status)
183         error_counter++;
184
185     /* Setup PAP, this PPP instance is effectively the since it generates the name and password
           for the peer..  */
186     status = nx_ppp_pap_enable(&ppp_client, generate_login, NX_NULL);
187
188     /* Check for PPP PAP enable error.  */
189     if (status)
190         error_counter++;
191
192     /* Attach an interface for PPP.  */
193     status = nx_ip_interface_attach(&ip_0, "Second Interface For PPP", IP_ADDRESS(0, 0, 0, 0), 0,
                                        nx_ppp_driver);
194
195     /* Check for error.  */
196     if (status)
197         error_counter++;
198
199     /* Enable ARP and supply ARP cache memory for Normal IP Instance.  */
200     status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
201     pointer = pointer + 1024;
202
203     /* Check for ARP enable errors.  */
204     if (status)
205         error_counter++;
206
207     /* Enable ICMP */
208     status = nx_icmp_enable(&ip_0);
209     if(status)
210         error_counter++;
211
212     /* Enable UDP traffic.  */
213     status =  nx_udp_enable(&ip_0);
214     if (status)
215         error_counter++;
216
217     /* Enable TCP traffic.  */
218     status =  nx_tcp_enable(&ip_0);
219     if (status)
220         error_counter++;
221
222     /* Create the main thread.  */
223     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
224                      pointer, DEMO_STACK_SIZE,
225                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
226     pointer =  pointer + DEMO_STACK_SIZE;
227
228 }
229
230 /* Define the test threads.  */
231
232 void    thread_0_entry(ULONG thread_input)
233 {
234 UINT    status;
235 ULONG   ip_status;
236
237     /* Create the PPPoE instance.  */
238     status =  nx_pppoe_client_create(&pppoe_client, (UCHAR *)"PPPoE Client",  &ip_0,  0,
        &pool_0, pointer, PPPOE_THREAD_SIZE, 4, _nx_ram_network_driver, pppoe_client_packet_receive);
239     pointer = pointer + PPPOE_THREAD_SIZE;
240     if (status)
241     {
242         error_counter++;
243         return;
244     }
245
246     /* Establish PPPoE Client sessione.  */
247     status = nx_pppoe_client_session_connect(&pppoe_client, NX_WAIT_FOREVER);
248     if (status)
249     {
250         error_counter++;
251         return;
252     }
253
254     /* Wait for the link to come up.  */
255     status = nx_ip_interface_status_check(&ip_0, 1, NX_IP_ADDRESS_RESOLVED,
                                              &ip_status, NX_WAIT_FOREVER);
256     if (status)
257     {
258         error_counter++;
259         return;
260     }
261
262     /* Get the PPPoE Server physical address and Session ID after establish PPPoE Session.  */
263     /*
264     status = nx_pppoe_client_session_get(&pppoe_client, &server_mac_msw,
                                             &server_mac_lsw, &session_id);
265     if (status)
266         error_counter++;
267     */
268 }
269
270 /* PPPoE Client receive function.  */
271 void    pppoe_client_packet_receive(NX_PACKET *packet_ptr)
272 {
273
274     /* Call PPP Client to receive the PPP data fame.  */
275     nx_ppp_packet_receive(&ppp_client, packet_ptr);
276 }
277
278 /* PPP Client send function.  */
279 void    ppp_client_packet_send(NX_PACKET *packet_ptr)
280 {
281
282     /* Directly Call PPPoE send function to send out the data through PPPoE module.  */
283     nx_pppoe_client_session_packet_send(&pppoe_client, packet_ptr);
284 }
285 #endif /* NX_PPPOE_CLIENT_INITIALIZE_DRIVER_ENABLE  */
286
287 #endif /* NX_PPP_PPPOE_ENABLE  */

图 1.1 与 NetX 配合使用的 PPPoE 客户端示例

配置选项

可通过几个配置选项生成构建适用于 NetX 的 PPPoE 客户端。 以下列表对每个配置选项进行详细说明:

  • NX_DISABLE_ERROR_CHECKING:定义后,此选项会删除基本的 PPPoE 客户端错误检查, 通常在调试应用程序完成后使用。
  • NX_PPPOE_CLIENT_INITIALIZE_DRIVER_ENABLE:定义后,此选项会启用在 PPPoE 模块中初始化以太网驱动程序的功能, 默认情况下则会禁用该功能。
  • NX_PPPOE_CLIENT_THREAD_TIME_SLICE:PPPoE 客户端线程的时间片选项。 默认情况下,此值为 TX_NO_TIME_SLICE。
  • NX_PPPOE_CLIENT_PADI_INIT_TIMEOUT:此选项定义初始重新传输 PADI 数据包的等待部分。 默认情况下,此值为 1 秒。
  • NX_PPPOE_CLIENT_PADI_COUNT:此选项定义在将连接视为中断之前允许的 PADI 传输停用次数。 默认情况下,此值为 4。
  • NX_PPPOE_CLIENT_PADR_INIT_TIMEOUT:此选项定义初始重新传输 PADR 数据包的等待部分。 默认情况下,此值为 1 秒。
  • NX_PPPOE_CLIENT_PADR_COUNT:此选项定义在将连接视为中断之前允许的 PADR 传输停用次数。 默认情况下,此值为 4。
  • NX_PPPOE_CLIENT_MAX_AC_NAME_SIZE:此选项定义 AC-Name 的最大大小。 默认情况下,此值为 32。
  • NX_PPPOE_CLIENT_MAX_AC_COOKIE_SIZE:此选项定义 AC-Cookie 的最大大小。 默认情况下,此值为 32。
  • NX_PPPOE_CLIENT_MAX_RELAY_SESSION_ID_SIZE:此选项定义 Relay-Session-Id 的最大大小。默认情况下,此值为 12。
  • NX_PPPOE_CLIENT_MIN_PACKET_PAYLOAD_SIZE:指定 PPPoE 客户端的最小数据包有效负载大小。 如果数据包有效负载大小大于此值,则可以避免数据包链接。 默认情况下,此值为 1520(以太网的最大有效负载大小 1500 + 以太网标头 14 + CRC 2 + 四字节对齐 4)。