You are on page 1of 656

Wind River Network Stack for VxWorks 6 Programmer's Guide

Wind River ®

Network Stack
for VxWorks 6 ®

P R O G R A M M E R ’S G U I D E

3.1
Copyright © 2006 Wind River Systems, Inc.
All rights reserved. No part of this publication may be reproduced or transmitted in any
form or by any means without the prior written permission of Wind River Systems, Inc.
Wind River, the Wind River logo, Tornado, and VxWorks are registered trademarks of
Wind River Systems, Inc. Any third-party trademarks referenced are the property of their
respective owners. For further information regarding Wind River trademarks, please see:
http://www.windriver.com/company/terms/trademark.html
This product may include software licensed to Wind River by third parties. Relevant
notices (if any) are provided in your product installation at the following location:
installDir/product_name/3rd_party_licensor_notice.pdf.

Corporate Headquarters
Wind River Systems, Inc.
500 Wind River Way
Alameda, CA 94501-1153
U.S.A.

toll free (U.S.): (800) 545-WIND


telephone: (510) 748-4100
facsimile: (510) 749-2010

For additional contact information, please visit the Wind River URL:
http://www.windriver.com
For information on how to contact Customer Support, please visit the following URL:
http://www.windriver.com/support

Wind River Network Stack for VxWorks 6 Programmer’s Guide, 3.1

28 Apr 06
Part #: DOC-15751-ZD-00
Contents

1 Overview ............................................................................................... 1

1.1 Introduction ............................................................................................................. 1


1.1.1 Installation ................................................................................................. 2
1.1.2 Building the Network Stack .................................................................... 2
1.1.3 Latest Release Information ..................................................................... 3
1.1.4 Additional Documentation ..................................................................... 3

1.2 Component Overview ........................................................................................... 4

1.3 About this Manual ................................................................................................. 6


1.3.1 Chapter Overviews .................................................................................. 6
1.3.2 About the IP Addresses Used in this Manual ...................................... 10

2 Configuring VxWorks for the Network Stack ..................................... 13

2.1 Introduction ............................................................................................................. 13

2.2 Adding Network Stack Configuration Components ...................................... 14


2.2.1 Including the Essential Components ..................................................... 14
2.2.2 Including Application Components ...................................................... 20

iii
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

2.2.3 Including a Network Driver ................................................................... 20


2.2.4 Additional Dependencies ........................................................................ 21

2.3 Configuring the Network Daemon Task ........................................................... 21

2.4 Testing Connectivity from the Target ................................................................. 23


Testing IPv4 Connectivity ....................................................................... 23
Testing IPv6 Connectivity ....................................................................... 25

3 Configuring and Managing Memory ................................................... 27

3.1 Introduction ............................................................................................................. 27

3.2 Configuring VxWorks for Network Memory Pools ........................................ 28


Network Stack Memory Pool Configuration ....................................... 28
linkBufPool ................................................................................................ 29
netBufPool ................................................................................................. 29
netBufLib ................................................................................................... 29
netBufAdvLib ........................................................................................... 30

3.3 Configuring Network Stack Pool Resources .................................................... 30


3.3.1 Estimating Memory Pool Usage ............................................................. 30
3.3.2 Mapping Configuration Parameters to netPoolInit( ) ......................... 32
3.3.3 Network Stack Memory Pool Configuration Parameters .................. 35

3.4 Managing Memory Buffers .................................................................................. 39


3.4.1 Understanding How netBufLib Pool Organizes Memory ................. 40
3.4.2 Working with the New Memory Pool API ........................................... 42
3.4.3 Working with the Original Memory Pool API ..................................... 45
Setting Up a Memory Pool in the Original Style ................................. 45
Storing and Using Data in Clusters ....................................................... 46
Freeing mBlks, clBlks, and Clusters ....................................................... 47
3.4.4 Using Macros for Buffer Manipulation ................................................. 47

iv
Contents

4 Modifying Parameters at Run-time ..................................................... 49

4.1 Introduction ............................................................................................................. 50

4.2 kern.ipc Variables ................................................................................................... 50

4.3 net.inet.icmp Variables .......................................................................................... 51

4.4 net.inet.ip Variables ............................................................................................... 52

4.5 net.inet.ip.portrange Variables ............................................................................ 54

4.6 net.inet.raw Variables ............................................................................................ 55

4.7 net.inet.sctp Variables ............................................................................................ 55

4.8 net.inet.tcp Variables ............................................................................................. 58

4.9 net.inet.tcp.syncache Variables ............................................................................ 62

4.10 net.inet.udp Variables ............................................................................................ 62

4.11 net.inet6.icmp6 Variables ...................................................................................... 63

4.12 net.inet6.ip6 Variables ........................................................................................... 65

4.13 net.link.ether.inet Variables ................................................................................. 68

5 Configuring Transport and Network Protocols ................................ 71

5.1 Introduction ............................................................................................................. 71

5.2 Configuring IPv4 Components ............................................................................ 73


TCP v4 ........................................................................................................ 73
TCP Debugging ........................................................................................ 77
UDP v4 ....................................................................................................... 77
IP v4 ............................................................................................................ 78
RAW v4 ...................................................................................................... 83
ICMP v4 ..................................................................................................... 83
Attach END to IPv4 ................................................................................. 85

v
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

5.3 Configuring IPv6 Components ............................................................................ 85


TCP v6 ........................................................................................................ 86
UDP v6 ....................................................................................................... 86
IP v6 ............................................................................................................ 86
RAW v6 ...................................................................................................... 89
ICMP v6 ..................................................................................................... 89
Attach END to IPv6 .................................................................................. 90

5.4 Configuring VxWorks for Network Show Routines ....................................... 91


TCP Show Routines ................................................................................. 91
UDP Show Routines ................................................................................. 91
ICMP Show Routines ............................................................................... 92
IGMP Show Routines ............................................................................... 92
Network IP Show Routines ..................................................................... 92
Network Interface Show Routines ......................................................... 92
Network Host Show Routines ................................................................ 92

6 Using SCTP ........................................................................................... 93

6.1 Introduction ............................................................................................................. 93

6.2 Building and Configuring for SCTP .................................................................. 95


6.2.1 Building the Network Stack to Support SCTP ..................................... 95
6.2.2 Configuring VxWorks for SCTP ............................................................. 96
SCTP ........................................................................................................... 96
Setting Configuration Parameters ......................................................... 96

6.3 Understanding the SCTP Transport Layer ........................................................ 99


RFC Information ....................................................................................... 100
TCP Shortcomings .................................................................................... 100
SCTP Advantages ..................................................................................... 100

6.4 Working with SCTP ............................................................................................... 102


6.4.1 Using the Extended Socket API for SCTP ............................................. 102
6.4.2 Monitoring and Controlling SCTP ......................................................... 106
6.4.3 Getting SCTP Status Information .......................................................... 107

vi
Contents

7 Enabling Virtual TCP/IP Stacks ........................................................... 111

7.1 Introduction ............................................................................................................. 111

7.2 Configuring VxWorks for Virtual Stacks .......................................................... 112


Virtual Stack Library ................................................................................ 113
Virtual Stack Core Initialization ............................................................. 114
Virtual Stack Application Initialization ................................................ 114
Old Virtual Stack Library Wrapper Routines ....................................... 114
Virtual Stack Show Routines .................................................................. 114
Virtual Stack Debug Support .................................................................. 115
Virtual Stack Example Code ................................................................... 115
Applications in Virtual Stack 0 Library ................................................. 115

7.3 Understanding Dual-Instance Network Stacks ................................................ 115


7.3.1 Using Common Object Code .................................................................. 116
Configuring VS0 ....................................................................................... 116
Configuring the Secondary Stack .......................................................... 116
Overriding Build-Time Configuration Parameter Values .................. 117
7.3.2 Stack Numbers versus VSIDs ................................................................. 117
7.3.3 Using Essential vsLib Routines .............................................................. 117
Configuring and Creating a New Virtual Stack Instance ................... 117
Setting Stack Context prior to Requesting Network Services ........... 119
Writing Task Routines for a Virtual Stack Environment .................... 119
Executing a Wind Shell Command in a Specific Stack Context ........ 119
Showing Stack Information .................................................................... 119
7.3.4 Using Sockets in Virtual Stacks .............................................................. 120

7.4 Starting a Secondary Stack Instance ................................................................... 120


Using the vsLib API ................................................................................. 120
Debugging and Exploring Virtual Stacks ............................................. 121

7.5 Using SNMP with Virtual TCP/IP Stack Instances ......................................... 122

7.6 Using sysctl with Virtual Stacks .......................................................................... 125

vii
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

8 Adding NFS Support ............................................................................ 127

8.1 Introduction ............................................................................................................. 127

8.2 Configuring VxWorks for an NFS Client .......................................................... 128


Core NFS Client ........................................................................................ 128
NFS Client All ........................................................................................... 129
NFS v2 Client ............................................................................................ 129
NFS v3 Client ............................................................................................ 130
NFS Mount All .......................................................................................... 133

8.3 Creating an NFS Client ......................................................................................... 133


Exporting File Systems from the Remote NFS Server ......................... 134
Setting Your NFS Client Name, User ID, and Group ID .................... 135
Mounting a Remote File System ............................................................ 135
Using IOCTL Routines for Open Files from a Mounted Directory ... 137

8.4 Configuring VxWorks for an NFS Server .......................................................... 139


NFS Server ................................................................................................. 139
NFS server All ........................................................................................... 140
NFS server V2 ........................................................................................... 140
NFS server V3 ........................................................................................... 141

8.5 Creating an NFS Server ......................................................................................... 143


Initializing an NFS File System for Export ........................................... 143
Exporting a File System through NFS ................................................... 143

9 Adding Support for Network Applications ......................................... 145

9.1 Introduction ............................................................................................................. 146

9.2 Ping ............................................................................................................................ 146


Configuring VxWorks for Ping ............................................................... 147
PING ICMP Client .................................................................................... 147
PING6 ICMP Client .................................................................................. 147

9.3 DNS ........................................................................................................................... 148


Wind River Implementation ................................................................... 148
Configuring VxWorks for DNS .............................................................. 149

viii
Contents

Domain Name Service Client ................................................................. 149


Domain Name Service Client Debug Output ...................................... 152

9.4 SNTP ......................................................................................................................... 152


Configuring VxWorks for SNTP ............................................................ 152
SNTP Client ............................................................................................... 153
SNTP Server .............................................................................................. 153

9.5 FTP ............................................................................................................................. 155


Configuring VxWorks for FTP ................................................................ 156
FTP Client .................................................................................................. 156
FTPv6 Server Security .............................................................................. 158
Anonymous FTP ....................................................................................... 158
FTP6 Client ................................................................................................ 159
FTP6 Server ................................................................................................ 160

9.6 TFTP .......................................................................................................................... 160


Configuring VxWorks for TFTP ............................................................. 161
TFTP Client ................................................................................................ 161
TFTP Server ............................................................................................... 162

9.7 RSH ........................................................................................................................... 163


Wind River Implementation ................................................................... 163
Configuring VxWorks for rsh ................................................................. 163
Remote Command ................................................................................... 164
Enabling Access to an RSH User ............................................................ 164

9.8 RPC ............................................................................................................................ 165


9.8.1 Wind River Implementation of RPC ...................................................... 165
9.8.2 Configuring VxWorks for RPC ............................................................... 166
RPC ............................................................................................................. 166
XDR ............................................................................................................ 166
XDR Boolean Support .............................................................................. 166

9.9 RLOGIN ................................................................................................................... 167


Configuring VxWorks for RLOGIN ....................................................... 167
RLOGIN ..................................................................................................... 167
Connecting to Host Systems ................................................................... 167
Using RLOGIN in an RTP ....................................................................... 168

ix
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

9.10 Telnet ......................................................................................................................... 168


Configuring VxWorks for Telnet ............................................................ 168
Telnet Server .............................................................................................. 169
Telnet Client .............................................................................................. 171
TELNET/FTP password protection ....................................................... 171
Using Telnet in an RTP ............................................................................ 171
Unsupported Commands and Options ................................................ 172

9.11 Changing the Default Login for FTP, FTPv6, and Telnet ................................ 173
9.11.1 Changing the Default Login Before You Build VxWorks ................... 174
Obtaining an Encrypted Password ........................................................ 174
Changing the user name and password in configAll.h ...................... 174
Changing the user name and password in Workbench ...................... 175
9.11.2 Changing the Default Login After You Build VxWorks ..................... 175

9.12 Creating a netDrv Device for RSH or FTP ......................................................... 176


Setting the User ID for Remote File Access with RSH or FTP ........... 177
Setting File Permissions on the Remote System .................................. 177
Creating a netDrv Instance ..................................................................... 177
Using netDrv to Download Run-Time Images .................................... 178

10 Working with DHCPv4 and DHCPv6 ................................................... 181

10.1 Introduction ............................................................................................................. 181

10.2 Configuring VxWorks for DHCPv4 .................................................................... 182


10.2.1 DHCPv4 Component Summary ............................................................ 182
DHCPv4 Run-time Client ....................................................................... 183
DHCPv4 Boot-Time Client ...................................................................... 185
DHCPv4 Client Timestamp Storage ...................................................... 186
DHCPv4 Client Lease Verification/Assignment ................................. 186
DHCPv4 Client Common Library ......................................................... 186
DHCP Client Show Routines .................................................................. 187
DHCP Relay Agent .................................................................................. 187
DHCP Shared Files for Server and Relay Agent .................................. 187
DHCP Server ............................................................................................. 188
DHCP Core files ....................................................................................... 189
10.2.2 Interface Settings Retrieved Using DHCPv4 ........................................ 189

x
Contents

10.3 Working with the DHCPv4 Client ...................................................................... 190

10.4 Working with the DHCPv4 Relay Agent ........................................................... 192


Configuring the Relay Agent to Find a Server .................................... 192
Identifying the Interfaces of Importance to the Relay Agent ............ 193
Configuring a Server to Accept Requests from Your Relay Agent ... 194

10.5 Working with the DHCPv4 Server ...................................................................... 195


Configuring a DHCPS Interfaces Table ................................................. 196
Configuring the Lease Table in the Wind River DHCP Server .......... 196
Configuring the Relay Agent Table in the Wind River DHCP Server 198
Storing and Retrieving Active Network Configurations ................... 198

10.6 Using DHCPv6 ........................................................................................................ 200


10.6.1 Wind River Implementation ................................................................... 201
10.6.2 Configuring VxWorks for DHCPv6 ....................................................... 201
DHCPv6 Run-time Client ....................................................................... 201
DHCPv6 Server ........................................................................................ 203
DHCPv6 Relay Agent .............................................................................. 204
DHCPv6 Client Show Routines ............................................................. 206

11 Creating Network Applications as RTPs ............................................ 207

11.1 Introduction ............................................................................................................. 207

11.2 Network Applications Supported in RTPs ....................................................... 208


11.2.1 DNS Resolver in an RTP .......................................................................... 209
11.2.2 FTP Server in an RTP ............................................................................... 209
11.2.3 FTP Client in an RTP ................................................................................ 209
11.2.4 Ping or Ping6 in an RTP .......................................................................... 210
11.2.5 Remote Command Library (remLib) in an RTP .................................. 210
11.2.6 RIP in an RTP ............................................................................................ 210
Starting the RIP RTP ................................................................................ 210
Shutting Down the RIP RTP ................................................................... 212
Managing the RIP RTP ............................................................................ 213
11.2.7 Rlogin Client in an RTP ........................................................................... 215

xi
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

11.2.8 Telnet Client in an RTP ............................................................................ 215


11.2.9 TFTP Client in an RTP .............................................................................. 215
11.2.10 TFTP Server in an RTP ............................................................................. 215
11.2.11 General Network/RTP Incompatibilities ............................................. 215

11.3 Working with Application RTPs ......................................................................... 216


11.3.1 Building an RTP ELF Object File for a Network Application ............ 217
Writing the Code for a “Hello World” RTP .......................................... 217
Building the Code for a “Hello World” RTP ........................................ 218
Setting up Pre-Entry-Point Initialization Routines .............................. 218
Not All Initialization Routines Are Suitable for Pre-Entry-Point
Initialization ............................................................................... 218
Writing the Code for an FTP RTP ........................................................... 219
Building the Code for the FTP RTP ........................................................ 220
11.3.2 Launching an RTP .................................................................................... 221
11.3.3 Identifying the RTP Initialization Routine in a Library ...................... 222
11.3.4 Shutting down an RTP Application ....................................................... 223

11.4 Using Socket Connections with RTPs ................................................................ 223


11.4.1 Configuring VxWorks for the SAL Library .......................................... 225
Socket Application Library Client ......................................................... 226
Socket Application Library Server ......................................................... 226
Socket Name Service Server in Kernel .................................................. 227
Socket Name Service Server in RTP ....................................................... 227
Socket Name Service Show Routine ...................................................... 228
11.4.2 Using the SAL Library ............................................................................. 228
11.4.3 Using SNS Clients and Servers ............................................................... 230

12 Working with Internet and Local Domain Sockets ............................ 231

12.1 Introduction ............................................................................................................. 231


VxWorks Environment-Specific Socket Issues ..................................... 232
Essential Background Reading ............................................................... 232
Include Files Referenced in this Chapter .............................................. 233

xii
Contents

12.2 Types of Sockets ..................................................................................................... 233


Internet Domain Sockets ......................................................................... 233
Routing Sockets ........................................................................................ 234
Local Domain Sockets .............................................................................. 234

12.3 Configuring VxWorks for Sockets ...................................................................... 235


Socket API ................................................................................................. 235
Socket API System Call Support ............................................................ 236
BSD Socket Support ................................................................................. 236

12.4 Using BSD Sockets under VxWorks ................................................................... 238


Supported Communications Domains ................................................. 238
Supported Socket Types .......................................................................... 239
Raw Sockets for Socket Type “Other” ................................................... 240

12.5 Working with Local Domain Sockets ................................................................. 240

12.6 Working with Internet Domain Sockets ............................................................ 242


12.6.1 Setting up an Internet Domain Socket under VxWorks ..................... 242
Creating a Socket Descriptor .................................................................. 242
Setting Socket Options ............................................................................. 243
Binding a Name to a Socket .................................................................... 244
12.6.2 Creating the Connection for Internet Domain Stream Sockets .......... 248
12.6.3 Sending and Receiving Data Using Internet Domain Sockets ........... 249
Sending and Receiving Data without Regard to the Control Data ... 249
Accessing and Setting the Control Data for a Socket Message .......... 250
12.6.4 Closing or Shutting Down an Internet Domain Socket Connection . 251
12.6.5 Support Routines for Working with Internet Addresses .................... 253

13 Writing Sample Applications Using Sockets ..................................... 255

13.1 Introduction ............................................................................................................. 255

13.2 Writing Applications Using Datagram Sockets (UDP) ................................... 255


13.2.1 Using a Datagram Socket to Implement a Client-Server System ...... 256
13.2.2 Using a Datagram (UDP) Socket to Access IPv4 Multicasting .......... 260

xiii
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

13.3 Writing Applications Using Stream Sockets (TCP) ......................................... 266

14 Using Fast UDP and Zbuf Sockets .................................................... 273

14.1 Introduction ............................................................................................................. 273

14.2 Fast UDP ................................................................................................................... 274


Configuring VxWorks for Fast UDP ...................................................... 274
Fast UDPv4 ................................................................................................ 274
Fast UDPv6 ................................................................................................ 275

14.3 Zbuf Sockets ............................................................................................................ 275


Configuring VxWorks for Zbuf Sockets ................................................ 276
ZBUF Socket .............................................................................................. 276
14.3.1 Using Zbuf Calls to Send Existing Data Buffers .................................. 277
14.3.2 Manipulating the Zbuf Data Structure .................................................. 277
Zbuf Byte Locations ................................................................................. 278
Creating and Destroying Zbufs .............................................................. 279
Getting Data In and Out of Zbufs .......................................................... 279
14.3.3 Operations on Zbufs ................................................................................ 280
14.3.4 Segments of Zbufs .................................................................................... 281
14.3.5 Manipulating the Zbuf Structure ........................................................... 282
14.3.6 Limitations of the Zbuf Implementation .............................................. 286
14.3.7 Calling Zbuf Socket Routines ................................................................. 286
Standard Socket Calls and Zbuf Socket Calls ....................................... 287
TCP Example Server Using Zbufs ......................................................... 287

15 Working with Routing Sockets ............................................................ 291

15.1 Introduction ............................................................................................................. 291

15.2 Getting Started with Routing Sockets ................................................................ 293


15.2.1 Configuring VxWorks for Routing Sockets .......................................... 293
15.2.2 Setting up a Routing Socket .................................................................... 293

xiv
Contents

15.3 Preparing and Processing Routing Socket Messages ...................................... 295


15.3.1 Case/Switch Processing for Received Messages ................................. 297
15.3.2 Types of Routing Socket Messages ........................................................ 298
15.3.3 RTF Flags ................................................................................................... 308

15.4 Extracting Information from a Routing Socket Message ............................... 310


15.4.1 Parsing the Routing Socket Message after the Header ....................... 311
15.4.2 Extracting TOS and Protocol IDs from a Received Message ............. 313

15.5 Building a Routing Socket Message ................................................................... 314


15.5.1 Setting the Header Structure Field Values ............................................ 315
15.5.2 Setting the TOS and Protocol Values in a Routing Socket Message . 319

16 Adding Routing Support .................................................................... 321

16.1 Introduction ............................................................................................................. 321

16.2 Selecting a Route Storage Mechanism ............................................................... 323

16.3 Configuring VxWorks for Route Storage .......................................................... 324


Route Storage ............................................................................................ 324
Network Route Show Routines .............................................................. 325

16.4 Working with RIP ................................................................................................... 326


16.4.1 Configuring VxWorks for RIP ................................................................ 327
Configuration Parameters ....................................................................... 328
Run-time Configuration .......................................................................... 330
16.4.2 Using RIP Debugging Routines ............................................................. 330
16.4.3 Creating an Interface Exclusion List for RIP ........................................ 331
RIP and Interface Status Changes .......................................................... 332
Responding to Route Table Changes by non-RIP Agents .................. 332
16.4.4 Writing a Sample Route Hook Callback Routine ................................ 336

16.5 Adding RIPng Support ......................................................................................... 338

xv
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

16.6 Adding ARP and NDP Support ........................................................................... 342


16.6.1 Configuring VxWorks for ARP .............................................................. 342
ARP Management .................................................................................... 342
Proxy ARP Server ..................................................................................... 343
16.6.2 Using NDP ................................................................................................ 346

16.7 Using the ICMPv4 Router Discovery Server ..................................................... 347

17 Using Fast IP Forwarding .................................................................... 351

17.1 Introduction ............................................................................................................. 351

17.2 Configuring VxWorks for Fast Path .................................................................... 352

17.3 Launching and Enabling a Fast Path Application ............................................ 354


17.3.1 Starting a Fast Path Application ............................................................ 354
17.3.2 Enabling Fast Forwarding ....................................................................... 355

17.4 Writing the Initialization Routine for a Fast Path Application ..................... 357
17.4.1 Allocating Resources for the fastPathLib Interface ............................. 357
17.4.2 Registering a Fast Path Application with fastPathLib ........................ 359

17.5 Populating and Maintaining a Fast Path FIB .................................................... 360


Populating a Fast Path FIB ...................................................................... 360
Maintaining a Fast Path FIB .................................................................... 361

17.6 Managing Your Fast Path Application ............................................................... 361

17.7 Writing Fast Path Application Entry Points ...................................................... 363

18 Adding IGMP, MLD, and Multicast Routing Support ......................... 375

18.1 Introduction ............................................................................................................. 375


IP Addressing ........................................................................................... 376
Multicast Routing Protocol ..................................................................... 377

xvi
Contents

18.2 Adding IGMP Host and Router Support ........................................................... 378


18.2.1 Compiling the Network Stack for IGMP .............................................. 378
18.2.2 Configuring VxWorks for IGMP ............................................................ 378
IGMP v4 ..................................................................................................... 378
Supported Join and Leave Group Options ........................................... 379
IGMP Router ............................................................................................. 380

18.3 Controlling Multicast Routing ............................................................................ 382

18.4 Adding and Deleting Virtual Interfaces for Multicast Routing .................... 383

18.5 Using the Advanced Multicast Routing API .................................................... 385

18.6 Using PIM ................................................................................................................ 392


What is PIM? ............................................................................................. 393
Using a Socket Interface to Enable and Access PIM Functionality ... 393

18.7 Configuring and Using MLD Hosts and Routers ........................................... 394
18.7.1 Compiling the Network Stack for MLD ............................................... 394
18.7.2 Configuring VxWorks for MLD ............................................................. 395
MLD ........................................................................................................... 395
IPv6 MLDv2 Proxy Router ...................................................................... 396
18.7.3 Build-Time Configuration Considerations ........................................... 397
18.7.4 Run-time Configuration Considerations .............................................. 397

19 ALTQ ...................................................................................................... 399

19.1 Introduction ............................................................................................................. 399

19.2 Supported Queueing Disciplines and Features ............................................... 400


19.2.1 Priority Queueing (PriorityQ) ................................................................ 401
19.2.2 Class-based queueing (CBQ) .................................................................. 401
CBQ Bandwidth ....................................................................................... 402
CBQ Priority .............................................................................................. 403
19.2.3 Random Early Detection (RED) ............................................................. 403

xvii
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

19.2.4 Explicit Congestion Notification (ECN) ................................................ 404


19.2.5 Token Bucket Regulator ........................................................................... 404

19.3 Compatibility with VxWorks Features ............................................................... 405

19.4 Building the Network Stack to Include ALTQ ................................................. 406


19.4.1 ALTQ Static Configuration Parameters ................................................ 408

19.5 The altqConfig Utility ........................................................................................... 410


19.5.1 Basic altqConfig Commands .................................................................. 411
19.5.2 Guidelines for Using altqConfig ............................................................ 412
19.5.3 The altqConfig queue Command and Subcommands ........................ 413
19.5.4 The altqConfig altqif Command and Subcommands ......................... 416

19.6 Rules and Rule Groups for Assigning Packets to Queues ............................. 419

19.7 Examples .................................................................................................................. 420


19.7.1 Class-Based Queueing Examples ........................................................... 420
Using altqConfig to Set Up CBQ Queues ............................................. 422
Defining Filter Rules for the CBQ Queues ........................................... 423
19.7.2 Priority Queueing Examples .................................................................. 424
Using altqConfig to Set Up Priority Queues ........................................ 425
Defining Filter Rules for the Priority Queues ...................................... 426
19.7.3 Sample Output from altqConfig ............................................................ 426
altqConfig "show" .................................................................................... 426
altqConfig "altqif if_name show stat" for CBQ .................................... 427
altqConfig "altqif if_name show stat" for Priority Queueing ............ 428

19.8 Sample Code for Pentium Processor Machine-Clock Routines .................... 428

20 Working with Device Instances .......................................................... 431

20.1 Introduction ............................................................................................................. 431

20.2 Working with Network Driver Instances .......................................................... 432


20.2.1 Attaching a Protocol to a Network Interface ........................................ 433

xviii
Contents

20.2.2 Configuring a Network Interface with an Address ............................ 434


Using ifconfig( ) ........................................................................................ 434
Using the ifLib API .................................................................................. 435
Using the if6Lib API ................................................................................ 436
20.2.3 Editing the Route Table ........................................................................... 436
20.2.4 Using routec( ) to Add or Delete Route Table Entries ......................... 437
20.2.5 Fixing Interfaces that Have Erroneous Addresses .............................. 438
20.2.6 Assigning a Host Name to an Address ................................................. 439
20.2.7 Configuring IPv4 Broadcast Addresses ................................................ 439
20.2.8 Bringing the Device Up for Link and Protocol Communication ....... 440
20.2.9 Configuring Router Advertisement and Solicitation for an Interface 440

20.3 Adding Automatic IPv4 Interface Configuration ............................................ 441


Configuring VxWorks for Auto IP ......................................................... 441
Using Auto IP ........................................................................................... 442

20.4 Using the Reverse ARP Client ............................................................................. 442


Configuring VxWorks for RARP Support ............................................ 442
Using the RARP Client ............................................................................ 443

20.5 Working with IPv4 and IPv6 Tunneling ............................................................ 444


20.5.1 Configuring VxWorks for Tunneling ..................................................... 444
GIF Tunnel Interface Driver .................................................................... 444
6to4 Tunnel Interface Driver ................................................................... 444
20.5.2 Using Tunneling Devices ........................................................................ 445
20.5.3 Using stf Devices to Create 6to4 Tunnels for IPv6 Packets ................ 447
20.5.4 Using gif Devices to Create RFC 2893-Style Configured Tunnels ..... 449
20.5.5 Extra Information in ICMP Error Messages ......................................... 452

20.6 Adding a BPF Device ............................................................................................. 453


Configuring VxWorks for BPF Support ................................................ 453
Creating a BPF Device ............................................................................. 453

xix
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

21 Integrating a New Network Interface Driver ....................................... 455

21.1 Introduction ............................................................................................................. 455

21.2 Configuring VxWorks for Network Interface Drivers .................................... 457


END Interface Support ............................................................................ 457
MUX Support ............................................................................................ 457

21.3 Overview of the MUX ............................................................................................ 458


21.3.1 The MUX and the OSI Network Model ................................................ 458
21.3.2 The Protocol-to-MUX Interface .............................................................. 460
21.3.3 The Data-Link-to-MUX Interface ........................................................... 461

21.4 How ENDs and NPT Drivers Differ ................................................................... 462


21.4.1 Managing Memory for Network Drivers and Services ...................... 464
21.4.2 Supporting Scatter-Gather in Your Driver ............................................ 464
21.4.3 Early Link-Level Header Allocation in an NPT Driver ...................... 465
21.4.4 MIB Statistics Collection in END and NPT Drivers ............................ 465
Configuring VxWorks for Counter Instrumentation .......................... 466
Calling the Driver Routines .................................................................... 467

21.5 Buffer Alignment ................................................................................................... 470


Copying the Data ..................................................................................... 471
Offsetting the Receive Buffers ................................................................ 471
Using a Scatter-Gather Receive .............................................................. 472

21.6 Understanding END Implementation ................................................................ 473


21.6.1 END Operation ......................................................................................... 473
Adding an END ........................................................................................ 473
Launching the Driver ............................................................................... 475
Binding to a Service ................................................................................. 475
Receiving Frames ..................................................................................... 476
21.6.2 The END Interface to the MUX .............................................................. 477
Data Structures Shared by the END and the MUX ............................. 477
END Entry Points Exported to the MUX .............................................. 478

xx
Contents

21.7 Understanding NPT Driver Implementation .................................................... 489


21.7.1 NPT Driver Operation ............................................................................. 489
Adding an NPT Driver ............................................................................ 490
Launching the Driver ............................................................................... 491
Responding to Network Service Bind Calls ......................................... 491
Receiving Frames ..................................................................................... 492
21.7.2 NPT Driver Interface to the MUX .......................................................... 493
Data Structures Used by the Driver ....................................................... 493
NPT Driver Entry Points Exported to the MUX .................................. 493

21.8 Porting a BSD Driver to the MUX ....................................................................... 504


21.8.1 Remove Unit Number References ......................................................... 504
21.8.2 Create an END Object to Represent the Device ................................... 504
21.8.3 Implementing the Standard END or NPT Entry Points ..................... 504
Rewrite xxattach( ) to Use an npt/endLoad( ) Interface .................... 506
The xxReceive( ) Routine Still Handles Task-Level Packets .............. 506
Rewrite xxOutput( ) to Use an npt/endSend( ) Interface .................. 506
The xxIoctl( ) Routine is the Basis of npt/endIoctl( ) .......................... 507
Implement All Remaining Required END or NPT Entry Points ....... 507

21.9 Supporting Multiple Network Interface Drivers ............................................. 507

21.10 Avoiding Memory Leaks ....................................................................................... 509

22 Integrating a New Network Service .................................................... 511

22.1 Introduction ............................................................................................................. 511

22.2 Writing a Network Service Sublayer .................................................................. 512


22.2.1 Initializing the Interface .......................................................................... 512
22.2.2 Data Structures and Resources ............................................................... 513
22.2.3 Sublayer Routines .................................................................................... 514
Sending Packets ........................................................................................ 514
Receiving Packets ..................................................................................... 515
Shutting Down an Interface .................................................................... 515

xxi
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Error Reporting ......................................................................................... 515


Flow Control ............................................................................................. 516
Device Control .......................................................................................... 516

22.3 Interfacing with the MUX ..................................................................................... 516


22.3.1 Service Routines Registered Using muxTkBind( ) .............................. 517
22.3.2 Service Routines Registered Using muxBind( ) ................................... 518

22.4 Adding a Socket Interface to Your Service ........................................................ 520


22.4.1 Process Overview ..................................................................................... 521
22.4.2 Implementing a Socket Back End .......................................................... 522
The Socket Functional Interface ............................................................. 522
The sockLibAdd( ) Routine ..................................................................... 523
22.4.3 Implementing Socket Routines .............................................................. 524
Implementation Recommendations a SOCK_FUNC Table ................ 524
Socket Routines Passed to iosDrvInstall( ) ........................................... 534

23 Working with the 802.1Q VLAN Tag ................................................... 537

23.1 Introduction ............................................................................................................. 537

23.2 Adding VLAN Support ......................................................................................... 538


23.2.1 Building VxWorks with VLAN Support ............................................... 538

23.3 Configuring VxWorks for 802.1Q VLAN Tagging ........................................... 539


MUX Layer 2 Support .............................................................................. 539
Subnet-Based VLAN ................................................................................ 540
L2Config .................................................................................................... 540

23.4 About the 802.1Q VLAN Tag Header .................................................................. 540

23.5 MUX Extensions for Layer 2 VLAN Support .................................................... 541


23.5.1 Overview of MUX-L2 Supported Functionality .................................. 542
23.5.2 Enabling VLAN Support for a Port ....................................................... 542
23.5.3 Attaching Non-Ethernet Devices ........................................................... 544
23.5.4 Disabling VLAN Support for a Port ...................................................... 544

xxii
Contents

23.5.5 MUX-L2 Ingress Rules ............................................................................. 544


23.5.6 MUX-L2 Egress Rules .............................................................................. 546
23.5.7 Accessing the MUX L2 Control Routines ............................................. 547

23.6 Current MUX-L2 Limitations ............................................................................... 547

23.7 VLAN Management ............................................................................................... 548


23.7.1 MUX-L2 VLAN Management ................................................................ 548
23.7.2 Socket-Based VLAN Management ........................................................ 550
23.7.3 Subnet-Based VLAN Management ....................................................... 553
Consequences of Changing the VID (applies to subnet VLAN only) 555
Examples of Subnet-based VLAN Management ................................. 555
23.7.4 Simultaneous Subnet-Based and Socket-Based VLANs ..................... 557

23.8 Using the MUX-L2 Show Routines ..................................................................... 558

23.9 Using the Deprecated VLAN Tag Library ......................................................... 560


Backward Compatibility ......................................................................... 561
Configuration Overview ......................................................................... 561
23.9.1 Configuring the Acceptable Ingress Frame Type Filter ...................... 562
23.9.2 Configuring the Egress Frame Type Filter ............................................ 562
23.9.3 Configuring the Ingress Rules ................................................................ 563
23.9.4 Configuring the Egress Rules ................................................................. 563
23.9.5 VLAN Tagged Frame Configuration Examples ................................... 564

A Glossary ................................................................................................ 567

A.1 Introduction ............................................................................................................. 567

A.2 Terms ......................................................................................................................... 567

A.3 Abbreviations and Acronyms .............................................................................. 573

xxiii
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

B MUX/NPT Routines and Data Structures ........................................... 577

B.1 Introduction ............................................................................................................. 577

B.2 MUX Routines ......................................................................................................... 577


B.2.1 muxAddrResFuncAdd( ) ......................................................................... 578
B.2.2 muxIfFuncAdd( ) ...................................................................................... 579
B.2.3 muxAddrResFuncDel( ) .......................................................................... 580
B.2.4 muxIfFuncDel( ) ........................................................................................ 580
B.2.5 muxAddrResFuncGet( ) .......................................................................... 580
B.2.6 muxIfFuncGet( ) ....................................................................................... 581
B.2.7 muxAddressForm( ) ................................................................................. 581
B.2.8 muxBind( ) ................................................................................................. 582
B.2.9 muxDevExists( ) ....................................................................................... 582
B.2.10 muxDevLoad( ) ......................................................................................... 583
B.2.11 muxDevStart( ) .......................................................................................... 583
B.2.12 muxDevStop( ) .......................................................................................... 584
B.2.13 muxDevUnload( ) ..................................................................................... 584
B.2.14 muxError( ) ................................................................................................ 584
B.2.15 muxIoctl( ) ................................................................................................. 585
B.2.16 muxMCastAddrAdd( ) ............................................................................ 585
B.2.17 muxMCastAddrDel( ) .............................................................................. 586
B.2.18 muxMCastAddrGet( ) .............................................................................. 586
B.2.19 muxTkBind( ) ............................................................................................ 586
B.2.20 muxTkDrvCheck( ) .................................................................................. 588
B.2.21 muxTkPollReceive( ) ................................................................................ 589
B.2.22 muxTkPollSend( ) ..................................................................................... 589
B.2.23 muxTkReceive( ) ....................................................................................... 590
B.2.24 muxTkSend( ) ............................................................................................ 591

xxiv
Contents

B.2.25 muxTxRestart( ) ........................................................................................ 592


B.2.26 muxUnbind( ) ........................................................................................... 592

B.3 Data Structures ........................................................................................................ 593


B.3.1 DEV_OBJ ................................................................................................... 593
B.3.2 END_ERR .................................................................................................. 594
B.3.3 END_OBJ ................................................................................................... 594
B.3.4 END_QUERY ............................................................................................ 598
B.3.5 LL_HDR_INFO ......................................................................................... 599
B.3.6 M2_INTERFACETBL ............................................................................... 599
B.3.7 mBlk ........................................................................................................... 600
B.3.8 MULTI_TABLE ......................................................................................... 601
B.3.9 NET_FUNCS ............................................................................................. 601

Index .............................................................................................................. 603

xxv
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

xxvi
1
Overview

1.1 Introduction 1
1.2 Component Overview 4
1.3 About this Manual 6

1.1 Introduction
The Wind River Network Stack is a dual IPv4/IPv6 network stack based on a port
of the KAME/FreeBSD TCP/IP release and some applications ported from
previous versions of the Wind River Network Stack. It contains support for the
UDP and TCP transport layer protocols, DHCPv4 and DHCPv6 host configuration
protocols, standard network application protocols such as Telnet and FTP, and fast
IP forwarding.

Features Unique to Wind River Platforms

While the Wind River General Purpose Platform supports the standard TCP/IP
and application protocols, some features are available only with the Wind River
Platforms builds of the network stack. This includes Platform for Industrial
Devices, Platform for Network Equipment, Platform for Consumer Devices, and
Platform for Automotive Devices. These additional features, listed below and
noted in the documentation, are not available with the Wind River General
Purpose Platform, VxWorks Edition:

1
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


Stream Control Transmission Protocol (SCTP)

Multi-Instance Virtual TCP/IP Stacks

Internet Group Management Protocol (IGMP)

IGMPv2 Router

IGMPv3 Host

ALTQ (ALTernate Queueing) Quality of Service (QoS)

Multicast Listener Discovery (MLD) and MLDv2
■ Support for 802-Style VLAN (802.1Q VLAN Tag)
If you have purchased one of the Wind River Platforms that supports these
features, Wind River Platforms Getting Started includes instructions on how to build
the network stack code to activate these features. Note that full routing is now
supported in all stacks.

NOTE: RIP is supported even in host stacks. Therefore, if you build the code as a
host stack, the stack includes RIP implementation and is capable of forwarding
packets. RIP and RIPng are included to support a machine that uses an internal
IP-based network to communicate among multiple internal devices.

1.1.1 Installation

This component is meant to be installed as part of a Wind River Platform product.


Full installation instructions are provided in the Wind River Platforms Installation
and Licensing User’s Guide.

1.1.2 Building the Network Stack

Underlying all variants of the Wind River Network Stack is one fully integrated
code base. Depending on how you build the code (and configure licensing), you
can activate or deactivate different features. Some components shipped with your
Platform are provided as source code, which you must compile before you can use
the component in a VxWorks image project. In some cases, changing configuration
options requires that you recompile the component source. If you have purchased
a Wind River Platform, you need to recompile the network stack code to activate
the Platform-specific features. For detailed component source compile instructions
and other information on how to build the network stack, see the Wind River
Platforms Getting Started.
The build process referred to here is not the VxWorks image build. That build
depends upon a set of pre-compiled network stack object modules. The build

2
1 Overview
1.1 Introduction

referred to here is the building of the network stack code in order to create that set
1
of object modules. Depending on how you build the network stack code, you can
expand the module set to include additional non-default functionality. You can
also build the network stack code to change the behavior of certain modules
already in the default set. For example, it is possible to rebuild the modules to
exclude Wind River System Viewer instrumentation.

1.1.3 Latest Release Information

The latest information on this release can be found in the release notes for your
Platform. Release notes are shipped with your Platform product and are also
available from the Wind River Online Support site:
http://www.windriver.com/support/
In addition, this site includes links to topics such as known problems, fixed
problems, documentation, and patches.

NOTE: Wind River strongly recommends that you visit the Online Support
website before installing or using this product. The Online Support website may
include important software patches or other critical information regarding this
release.

For information on accessing the Wind River Online Support site, see the Customer
Services section of your Platform getting started guide.

1.1.4 Additional Documentation

The focus of this manual is the configuration of the Wind River Network Stack.
Although this manual includes some networking background information, it is
beyond the scope of this manual to provide a thorough description of socket usage,
routing, protocol implementation, writing a network interface driver, and
interpreting statistics returned by routines. For information of that sort, consider
the following sources:

The Design and Implementation of the 4.4 BSD Operating System, by Marshall Kirk
McKusick, Keith Bostic, Michael J. Kraals, John S. Quarterman

TCP/IP Illustrated, Vol. 1, by Richard Stevens

TCP/IP Illustrated, Vol. 2, by Gary Wright and Richard Stevens

3
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


Internetworking with TCP/IP Volume III, by Douglas Comer and David Stevens.

UNIX Network Programming, by Richard Stevens
(for information on socket programming)

Implementing IPv6, by Mark A. Miller, P.E.
In addition, you will want to visit The IPv6 Forum Web site:
http://www.ipv6forum.com

1.2 Component Overview


The Wind River Network Stack supports IPv4 and IPv6 protocols, and standard
socket connections defined using either IPv4 or IPv6 addresses. Dual IPv4/IPv6
stacks are an essential element of the transition from the current IPv4-based
Internet to an IPv6-based Internet. A dual IPv4/IPv6 host stack supports both
IPv4-based and IPv6-based network applications. In addition, if the host stack
supports an IPv6-based network application, but no local router provides IPv6
routing services, a host stack can tunnel through the IPv4 Internet to a remote dual
stack that does provide IPv6 routing services.
The implementations of standard applications for remote access, such as ftp, rsh,
and so on, have been upgraded to handle both IPv4 and IPv6 addresses. Within a
four-layer model, IP is the network layer:

Application – Telnet, FTP, and others

Transport – TCP, UDP, and SCTP

Network – IPv4, IPv6

Link – the MUX, network interface drivers
The four-layer model mentioned above describes the data plane functionality of a
TCP/IP stack. The data plane describes how the TCP/IP stack organizes the flow
of data from an application, down through the stack, out onto the network, and
then back. As packets flow down the stack, each layer adds a header to the packet
and pushes the packet down to the next level. As packets flow up the stack, each
layer strips its header, uses the header to determine the recipient of the packet, and
pushes the packet up to the appropriate recipient in the next higher layer.
If the packet expires, or IP cannot deliver a packet, IP generates an Internet Control
Message Protocol (ICMP) error message. IP uses its data plane functionality to

4
1 Overview
1.2 Component Overview

transmit this message, but the message itself is processed by the TCP/IP control
1
plane functionality. The control plane functionality of the TCP/IP stack allows the
protocols to detect transmission failures and monitor connectivity. Control plane
functionality is provided by the ICMP protocol.

SNMP

To support the Simple Network Management Protocol (SNMP), the Wind River
Network Stack includes standard MIBs for IPv4, UDP, TCP, ICMP, and the
network interfaces. The source code was instrumented for early versions of the
IPv6 MIBs that are now obsolete. This instrumentation is unsupported.
Also included is m2IfLib and m2IfMgtLib. These libraries provide MIB 2 services
for the interface group. Thus, they provide routines to initialize the group, access
the group scalar variables, read the table interfaces and change the state of the
interfaces. The externally callable routines associated with this configuration
component are described in the m2IfLib reference entries.
For more information, see 7.5 Using SNMP with Virtual TCP/IP Stack Instances,
p.122.

Run-Time Network Stack Configuration and Monitoring Utilities

Included with VxWorks are implementations of the UNIX-style network stack


configuration and monitoring utilities:
■ netstat( ) – report network status
■ Sysctl( )/sysctl( ) – set and get stack configuration parameters at run-time
(These system control routines are generic utilities that you can use to change
the value of network stack variables. These system control routines are not
specific to the network stack.)
For more information about using these utilities to set and monitor variables are
run-time, see 4. Modifying Parameters at Run-time.

MIB-II Libraries for IPv6 Included but not Supported

This stack includes libraries that provide the instrumentation code needed to
support the MIBs associated with RFC 2452 (TCP), RFC 2454 (UDP), RFC 2465
(IPv6), and RFC 2466 (ICMPv6). The IETF is revising these RFCs. These revisions
will make the current instrumentation code obsolete. For this reason, the
m2Ipv6NameLib libraries are not supported for this stack. Similarly, the MIB for
MLD is unsupported.

5
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

For more information, see 7. Enabling Virtual TCP/IP Stacks and 21. Integrating a
New Network Interface Driver.

1.3 About this Manual


The chapters in this manual begin with basic configuration components required
to build a minimal network stack that you can test for connectivity. As much as
possible, chapters are grouped together by topic. The organization of the book is
as follows, with some chapters spanning several subjects:

Overview, this chapter

Basic Configuration, Chapters 2 through 4

Transport and Network Layer Topics, Chapters 5 through 7

Applications, Chapters 8 through 11

Sockets, Chapters 12 through 15

Routing, Chapters 15 through 18

ALTQ, Chapter 19

MUX programming, Chapters 20 through 23

1.3.1 Chapter Overviews

Summaries of the chapters follow.

1. Overview

This chapter provides an overview of the Wind River Network Stack, including a
list of the features that are unique to the Wind River Platforms builds of the
network stack. It also summarizes the topic of each chapter of the programming
guide (this manual).

2. Configuring VxWorks for the Network Stack

This chapter describes how to include the minimum number of network stack
components needed to create a ping-responsive network stack.

6
1 Overview
1.3 About this Manual

3. Configuring and Managing Memory


1
This chapter documents how to manage the build time configuration of the
network stack’s system memory pool and data memory pool. It also provides
guidance for setting configuration parameters.

4. Modifying Parameters at Run-time

This chapter lists the network stack configuration variables whose values can be
changed at run-time. Default values for these variables are set at build time, and
not all of these variables can be meaningfully reset at run-time. For example,
configuration parameters that determine the size of a memory pool cannot be
meaningfully reset at run-time. Parameters that control behaviors, such as
enabling IP redirects, can be reset at run-time.

5. Configuring Transport and Network Protocols

This chapter documents the configuration components that implement the


protocols for the transport and network OSI layers. Components are documented
within the IPv4 or the IPv6 network protocol suite and include descriptions of the
configuration parameters associated with these components. This chapter also
covers the components that include the network show routines.

6. Using SCTP

This chapter describes how to configure and use the Wind River implementation
of SCTP, a transport layer protocol that provides services not available from either
TCP or UDP. This chapter assumes that you are familiar with the SCTP protocol as
described in RFC 2960 and its companion documents.

NOTE: SCTP is only available in the Wind River Platforms builds of the network
stack.

7. Enabling Virtual TCP/IP Stacks

This chapter describes how to configure and use virtual TCP/IP stacks with IPv6.
Virtual stacks let you run two TCP/IP stack instances on a single VxWorks target.
Each stack instance is data-independent and is designed to guarantee privacy at
the network layer.

NOTE: The virtual TCP/IP stacks feature is only available in the Wind River
Platforms builds of the network stack.

7
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

8. Adding NFS Support

This chapter covers the Network File Service (NFS), used access to file systems on
remote networked hosts. The Wind River implementation currently supports
Versions 2 and 3.

9. Adding Support for Network Applications

The Wind River Network Stack implements standard and remote network
application protocols that handle domain name lookup (DNS), file transfer (FTP,
TFTP), remote login (RLOGIN), remote execution (RSH), remote procedure call
(RPC), telnet, and so on. This chapter describes how to include these protocols in
a VxWorks image and configure them for use with the network stack.

10. Working with DHCPv4 and DHCPv6

This chapter provides per-component descriptions of all the components


associated with the Wind River DHCPv4 and DHCPv6 implementations.

11. Creating Network Applications as RTPs

This chapter focuses on network applications and services that have been ported
to RTPs. Also included are some recommendations on how to port your network
application to operate within an RTP.

12. Working with Internet and Local Domain Sockets

This chapter describes how to use the standard BSD socket interface in the Internet
domain. The Wind River Network Stack supports a standard BSD socket interface
to TCP and UDP. Using these sockets, you can:
■ Communicate with other processes.
■ Access the IP multicasting functionality.
Also described in this chapter are local domain sockets (AF_LOCAL sockets) based
on the COMP protocol, which provides message-oriented reliable communication
among processes on the same node.

13. Writing Sample Applications Using Sockets

This chapter focuses on how to write applications using UDP (datagram) and TCP
(stream) sockets.

8
1 Overview
1.3 About this Manual

14. Using Fast UDP and Zbuf Sockets


1
This chapter documents Fast UDP and zbuf sockets, both of which are fast
alternatives to using the standard socket interface. Fast UDP is a simple API,
targeted at quickly sending and receiving data over UDPv4 or UDPv6. Zbuf
sockets are used to read and write UNIX BSD sockets without copying data
between application buffers and network buffers.

15. Working with Routing Sockets

This chapter describes how to use a routing socket to make and monitor changes
in the content of the route table.

16. Adding Routing Support

This chapter tells you how to select a route table storage mechanism. It also
describes some of the protocols used to maintain the contents of the route table.
This chapter includes discussions of RIP, RIPng, ARP, NDP, and ICMPv4.

17. Using Fast IP Forwarding

This chapter describes how to use a fast IP-forwarding mechanism, also known as
a fast path application, which intercepts packets before they are passed up to IP.

18. Adding IGMP, MLD, and Multicast Routing Support

This chapter documents IGMP and MLD, which are used to support multicasting
in IPv4 and IPv6 domains, respectively. The Wind River General Purpose
Platform, VxWorks Edition, supports the IGMPv2 host and the MLDv1 host.

NOTE: The IGMPv2 router, IGMPv3 host, and the MLDv2 host and router are
available only in the Wind River Platforms builds of the network stack. See Features
Unique to Wind River Platforms, p.1.

19. ALTQ

This chapter describes ALTQ (ALTernate Queueing), which provides queuing


disciplines and other features that are useful for supporting network Quality of
Service (QoS).

20. Working with Device Instances

In addition to drivers supplied for the physical network interfaces, the Wind River
Network Stack also includes drivers for the creation of stf, gif, and BPF devices.
This chapter provides instruction and some background information on how to

9
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

create and configure device instances associated with the network stack. This
includes:

network interface instances for communication with the local network

gif pseudo devices for general purpose tunneling through the IPv4 Internet

stf pseudo devices for “6 to 4” tunneling through the IPv4 Internet

BSD (Berkeley) Packet Filter (BPF) devices for filtering incoming packets

21. Integrating a New Network Interface Driver

The Wind River Network Stack supports all network interface drivers currently
compatible with VxWorks 5.5. Although the Wind River Network Stack is based
on the KAME/FreeBSD TCP/IP release, the stack does not support drivers based
on the BSD 4.3 or 4.4 models. If you must use such a driver, you must port the
driver to the MUX interface model, as described in this chapter.

22. Integrating a New Network Service

A network service is an implementation of the network and transport layers of the


OSI network model. Under the Wind River Network Stack, network services
communicate with the data link layer through the MUX interface.This chapter
describes how to integrate a new network service with the MUX and, thus, with
the network stack.

23. Working with the 802.1Q VLAN Tag

This chapter describes the implementation of 802.1Q VLAN tagging for VxWorks
and tells you how to configure VxWorks to include this feature.

NOTE: The 802.1Q VLAN tagging feature is only available in the Wind River
Platforms builds of the network stack.

1.3.2 About the IP Addresses Used in this Manual

When working with the examples in this manual, you may find it convenient to cut
and paste example text into source code or to a command line. To avoid disrupting
the use of IPv4 or IPv6 addresses that are or might be put into service, the examples
in this manual restrict themselves to the following address spaces:

10/24 - one part of the private address space

127.0/8 - loopback addresses

169.254/16 - link local addresses

172.16/12 - another part of the private address space

10
1 Overview
1.3 About this Manual


192.0.2/24 - test and documentation addresses
1

192.168/16 - another part of the private address space

2001:DB8::/32 - test and documentation addresses (RFC 2849)

FE80::/10 - link local addresses

11
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

12
2
Configuring VxWorks
for the Network Stack

2.1 Introduction 13
2.2 Adding Network Stack Configuration Components 14
2.3 Configuring the Network Daemon Task 21
2.4 Testing Connectivity from the Target 23

2.1 Introduction
You can configure components for VxWorks in either of two ways. You can use the
Wind River Workbench to include components into your VxWorks image or you
can use the vxprj command-line tool to configure your project. Both facilities
handle dependencies for you.
To add a component from Workbench, you can use the Find tool to navigate to the
component in the configuration editor. For instructions on using Workbench to
include configuration components, see the Wind River Workbench User's Guide. For
instructions on adding configuration components using the vxprj command-line
tool, see the VxWorks Command-Line Tools User's Guide.

13
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

2.2 Adding Network Stack Configuration Components


There are over a hundred different configuration components associated with the
Wind River Network Stack. In Workbench, these components are organized into
the following functionally related groups and subgroups:

Core Network Components

Network Protocol Components
– SYSCTL Components
– Network IPv4 Components
– Network IPv6 Components
– Network Components for MIB-II

Network Device Components

Network Socket Components

Network Applications
– DHCP Application Components
– RPC Components
– NFS Components
– Network Host Utilities

Network Utility Components
– Network Show Routine Components
– netstat( ) Components
– Ifconfig Components

Network Private Components

Virtual Stack Support
This section lists the minimal network configuration components needed to create
a stack with just enough resources to respond to a ping or ping6 request. This lets
a remote system test the network connection to your target. Since, you cannot test
network connectivity from a target running a minimal stack without adding ping,
ping or ping6 are also included in the list of essential components.

2.2.1 Including the Essential Components

To build a minimal network stack, include the components in this list. Both
Workbench and vxprj will automatically include the component dependencies. All
components listed below and their required components are needed to build a
minimal network stack. If a component contains configuration parameters, you
may need or want to modify them.

14
2 Configuring VxWorks for the Network Stack
2.2 Adding Network Stack Configuration Components

This section includes components required to build both the IPv4 or an IPv6
network stack. To build only an IPv4 stack, you can optionally omit the IPv6
components. 2

INCLUDE_BSD_SOCKET

This component is needed to support standard BSD Internet Domain sockets and
is documented in BSD Socket Support, p.236 with its associated configuration
parameters. This component requires the following components:
■ INCLUDE_SOCKLIB, documented in Socket API, p.235.
■ INCLUDE_NET_POOL, documented in Network Stack Memory Pool
Configuration, p.28 with its associated configuration parameters.
The INCLUDE_NET_POOL component is automatically included with the
INCLUDE_BSD_SOCKET component. INCLUDE_NET_POOL itself requires and
pulls in the following essential configuration components:
■ INCLUDE_NETBUFLIB
■ INCLUDE_NETBUFPOOL
These components are also fully documented in Network Stack Memory Pool
Configuration, p.28.

INCLUDE_ETHERNET

This component is needed to support Ethernet interfaces. This component pulls in


etherMultiLib and other modules that define functions that network interface
drivers can use to manage a list of Ethernet multicast addresses. This component
requires the following components:

INCLUDE_MUX, documented in MUX Support, p.457.

INCLUDE_END, documented in END Interface Support, p.457.
There are no configuration parameters associated with the INCLUDE_ETHERNET
component.

INCLUDE_GTF_TIMER_START

This component automatically starts the General Timer Facility. This component
requires the following component:

INCLUDE_GTF, which pulls in modules that support the General Timer
Facility. INCLUDE_GTF has no configuration parameters.

15
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

There are no configuration parameters associated with the


INCLUDE_GTF_TIMER_START component.

INCLUDE_INETLIB

This component pulls in inetLib and other modules that implement routines for
manipulating Internet addresses, including the UNIX BSD inet_ routines. It
includes routines for converting between character addresses in Internet standard
dotted decimal notation and integer addresses, routines for extracting the network
and host portions out of an Internet address, and routines for constructing Internet
addresses given the network and host address parts.
There are no component dependencies or configuration parameters associated
with this component. For information on the externally callable functions
associated with this component, see the inetLib reference entry.

INCLUDE_ICMPV4

This component pulls in icmpLib and other modules that implement ICMP for
IPv4 and is documented in ICMP v4, p.83. This component requires the following
component:
■ INCLUDE_IPV4, documented in IP v4, p.78.

INCLUDE_ICMPV6

This component pulls in icmpv6Lib and other modules that implement ICMPv6.
This component is documented in ICMP v6, p.89. The INCLUDE_ICMPV6
component requires the following component:
■ INCLUDE_IPV6, documented in IP v6, p.86.
The INCLUDE_ICMPV6 component is only required for an IPv6 stack.

INCLUDE_IPATTACH

This component configures the IPv4 stack to automatically attach to the network
interface specified in the boot line parameters. This component is documented in
Attach END to IPv4, p.85. The INCLUDE_IPATTACH component requires the
following component:

INCLUDE_IPV4, documented in IP v4, p.78.

INCLUDE_IP6ATTACH

This component configures the IPv6 stack to automatically attach to the network
interface specified in the boot line parameters. This component and its associated

16
2 Configuring VxWorks for the Network Stack
2.2 Adding Network Stack Configuration Components

configuration parameters are documented in Attach END to IPv6, p.90. The


INCLUDE_IP6ATTACH component requires the following component:
2

INCLUDE_IPV6, documented in IP v6, p.86.
The INCLUDE_IP6ATTACH component is only required for an IPv6 stack.

INCLUDE_IPV4 and INCLUDE_IPV6

These components are essential to a minimal network stack build, however, you
do not need to explicitly include them; they are automatically pulled in as
dependencies of several essential network stack components. These components
also require the following essential configuration components that are also
automatically included:
■ INCLUDE_LOOPBACK

INCLUDE_ND (IPv6 only)

INCLUDE_ROUTE

INCLUDE_ROUTE_STORAGE, documented in 16.3 Configuring VxWorks for
Route Storage, p.324.
The INCLUDE_IPV6 and the INCLUDE_ND components are only required for an
IPv6 stack.

INCLUDE_MIB2_IF

This component pulls in modules and MIB files that SNMP needs to provide access
to the network interface layer. This component and its associated configuration
parameters are documented in Configuring VxWorks for Counter Instrumentation,
p.466. There are no component dependencies for this component.

INCLUDE_MLD

This component adds support for the MLD host. This component and its
associated configuration parameters are documented in MLD, p.395. The
INCLUDE_MLD component requires the following component:

INCLUDE_IPV6, documented in IP v6, p.86.
The INCLUDE_MLD component is only required for an IPv6 stack.

17
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

INCLUDE_NBIO_LOG

This component is an operating system component for non-blocking message


logging. It contains one configuration parameter, INIT_NBIO_MSGS, which
determines the initial number of NBIO buffers. The default value is 32.

INCLUDE_NET_BOOT_CONFIG

This component configures a network interface based on the device configuration


parameters in the boot line.
This component has no associated configuration parameters and requires the
following components:
■ INCLUDE_NET_BOOT, which pulls in code that copies boot line parameters to
locations that are accessible to INCLUDE_IPATTACH and
INCLUDE_NET_BOOT_CONFIG. It has no associated parameters and requires
the INCLUDE_NETMASK_GET component.
■ INCLUDE_SOCKLIB documented in Socket API, p.235.
■ INCLUDE_NET_INIT, which initializes the static tables used by the network
stack and requires the INCLUDE_NETWORK component.

INCLUDE_NET_DAEMON

This component pulls in the software modules needed for tNetTask and is
documented in 2.3 Configuring the Network Daemon Task, p.21.

INCLUDE_NET_REM_IO

This component pulls in modules that initialize systems in support of file access on
the boot host. This component supports the activities of components such as
INCLUDE_NET_DRV and requires the following configuration components:
■ INCLUDE_NET_DRV

INCLUDE_BOOT_LINE_INIT

INCLUDE_NET_BOOT

INCLUDE_NET_HOST_SETUP

For more information on how to use netDrv, see the netDrv reference entry and
9.12 Creating a netDrv Device for RSH or FTP, p.176.

18
2 Configuring VxWorks for the Network Stack
2.2 Adding Network Stack Configuration Components

INCLUDE_PING

This component pulls in support for the ping utility with IPv4 and is documented
2
in PING ICMP Client, p.147.

INCLUDE_PING6

This component pulls in support for the ping utility with IPv6 and is documented
in PING6 ICMP Client, p.147. This component is only required for an IPv6 stack.

INCLUDE_RAWV4

This component pulls in modules to support raw IPv4 sockets. This component is
documented in RAW v4, p.83 and requires the INCLUDE_IPV4 component,
documented in IP v4, p.78.

INCLUDE_RAWV6

This component pulls in modules in support of raw IPv6 sockets. There are no
user-callable functions or configuration parameters associated with this
component. This component is documented in RAW v6, p.89 and requires the
INCLUDE_IPV6 component, documented in IP v6, p.86.
The INCLUDE_RAWV6 component is only required for an IPv6 stack.

INCLUDE_NET_SYSCTL

This component pulls in the sysctlLib module and adds network system control
support. This component requires INCLUDE_SYSCTL and has no configuration
parameters.

INCLUDE_TCPV4

This component pulls in tcpLib and the other modules that provide IPv4 support
for TCP. This component is documented in TCP v4, p.73 and requires the
INCLUDE_IPV4 component, documented in IP v4, p.78.

INCLUDE_TCPV6

This component provides IPv6 support for TCP. This component is documented in
TCP v6, p.86 and requires the INCLUDE_IPV6 component, documented in IP v6,
p.86.
The INCLUDE_TCPV6 component is only required for an IPv6 stack.

19
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

INCLUDE_UDPV4

This component pulls in udpLib and other modules that implement UDP over
IPv4. This component requires the INCLUDE_IPV4 component. This component
and its associated configuration parameters are documented in UDP v4, p.77.

INCLUDE_UDPV6

This component implements UDP over IPv6 . This component requires the
INCLUDE_IPV6 component. This component and its associated configuration
parameters are documented in UDP v6, p.86.
The INCLUDE_UDPV6 component is only required for an IPv6 stack.

INCLUDE_XDR

This component pulls in modules that implement generic XDR (External Data
Representation) routines. It is automatically included as a requirement for RPC.
This component is required only if you also include WDB_COMM_SERIAL. For
more information, see XDR, p.166.

2.2.2 Including Application Components

The minimal run-time stack described above assumes that you run no application
other than ping or ping6. If you want to run an application, you will probably
want the default stack components (at the very least), which includes all of the
above plus the following:
INCLUDE_DHCPC_LEASE_CLEAN
INCLUDE_APPL_LOG_UTIL
INCLUDE_NET_GETOPT
INCLUDE_STRICMP

2.2.3 Including a Network Driver

To make the stack usable, it must include at least one network driver and
INCLUDE_MIILIB (the Media Independent Interface (MII) library). This module
implements a Media Independent Interface (MII) library. MII provides an
easy-to-implement connection between the Carrier Sense Multiple Access with
Collision Detection (CSMA/CD) media access controllers and the Physical Layer
Entities (PHYs). The purpose of this library is to provide Ethernet drivers in
VxWorks with a standardized and MII-compliant interface to various PHYs.

20
2 Configuring VxWorks for the Network Stack
2.3 Configuring the Network Daemon Task

Using the services of this library, network drivers can scan the existing PHYs, run
diagnostics, electrically isolate a subset of them, and negotiate their technology
abilities with other link-partners on the network. In short, this library lets you 2
initialize and configure a specific PHY in a proper MII-compliant fashion.
You can include an interface driver by editing the BSP’s config.h or configAll.h
file to define items such as INCLUDE_FEI82557END or INCLUDE_EL3C90XEND.
In addition, for IPv6, you may want to set up a tunnel to a remote IPv6 destination
if no IPv6 router is available locally. For information on how to do this at run-time,
see 20. Working with Device Instances.

2.2.4 Additional Dependencies

A minimal stack to which you have added the components listed in this chapter
will support a ping or ping6 made from the stack using the host shell. However,
you cannot use the kernel shell because that feature is not part of the minimal
default stack, although you can add it in if you want.

NOTE: If you include the DNS resolver, INCLUDE_DNS_RESOLVER, you need to


specify configuration values that are appropriate for your environment. The
default values are mere placeholders. They allow a build to succeed, but they do
not result in a working DNS resolver. For more information, see 9.3 DNS, p.148.

2.3 Configuring the Network Daemon Task


Under VxWorks, tNetTask. implements the network daemon. This task is
dedicated to handling the task-level (as opposed to interrupt-level) processing
required by the network stack. The ISR associated with a network driver uses
netJobAdd( ) to queue packet-processing work on this task. Because netJobAdd( )
is not normally available for general use, no reference entry is available for
netJobAdd( ). Information on how to use this function in an END or NPT driver,
is included in 21. Integrating a New Network Interface Driver.
To configure tNetTask, use the INCLUDE_NET_DAEMON configuration
component. This component supplies parameters that you can use to specify the
network task priority, stack size, and task options. This component also lets you
control the size of the tNetTask job queue.

21
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This component includes the following configuration parameters:

NET_JOB_NUM_CFG

Synopsis: The number of jobs allowed in the network daemon queue.


Default: 85

NET_TASK_PRIORITY

Synopsis: Task priority for tNetTask.


Default: 50

For the most part, you should not need to adjust any of these parameters. If you
think you need to adjust the task priority consider the following. By default,
tNetTask runs at a priority of 50. If you launch a task that depends on network
services, make sure your new task runs at a lower priority than that of tNetTask.1
When assigning a priority to a task dependent upon network services, keep in
mind the following:

An ISR interrupts even a priority 0 task.

When tNetTask is the highest priority task ready to run, it runs.

If a user task with a priority greater than tNetTask is ready, it runs instead of
tNetTask.2

While tNetTask does not run, packets are not processed, although ISRs
continue to receive the packets.
You must also consider the hazards of priority inversion. After a task takes a
semaphore with priority inversion protection, its task priority is elevated if
another higher priority task tries to take the semaphore. The new task priority is
equal to that of the highest priority task waiting for the semaphore. This priority
elevation is temporary. The priority of the elevated task drops back down to its
normal level after it releases the semaphore with priority inversion protection.
If a task dependent on tNetTask takes a semaphore with priority inversion
protection, and if a higher priority task subsequently tries to take the same

1. Changes to the TFTP client make it necessary that the application run at a priority less than
that of tNetTask. Otherwise, calls such as tftpXfer( ) will fail. This change is consistent
with the general advice that network applications should run at a priority less than that of
tNetTask. Previously, the TFTP client would work even if it was running at a higher
priority.
2. Only user tasks with priority greater than tNetTask, numerically less than 50, can
pre-empt tNetTask.

22
2 Configuring VxWorks for the Network Stack
2.4 Testing Connectivity from the Target

semaphore, the tNetTask-dependent task inherits the higher task priority. Thus, it
is possible for a network-dependent task to elevate in priority beyond that of
tNetTask. This locks tNetTask out until after the tNetTask-dependent task gives 2
back the problematic semaphore or semaphores.

NOTE: For more information on priority inversion protection and semaphores, see
the reference entry for semMLib.

NET_TASK_STACKSIZE

Synopsis: Stack size for tNetTask.


Default: 10000

For more information on valid stack size values, see the taskSpawn( ) reference
entry.

NET_TASK_OPTIONS

Synopsis: Options specified in the taskSpawn( ) call for tNetTask.


Default: VX_SUPERVISOR_MODE | VX_UNBREAKABLE

For more information on valid task options, see the taskSpawn( ) reference entry.

2.4 Testing Connectivity from the Target


You can use the ping( ) utility from a target to test whether a particular system is
accessible over the IPv4 or IPv6 Internet. Like the UNIX command, the VxWorks
ping( ) implementation sends one or more packets to another system and waits for
a response. You can identify the other system by either its name or its numeric
Internet address. This feature is useful for testing routing tables and host tables, or
determining whether another machine is receiving and sending data.

Testing IPv4 Connectivity

The following example shows ping( ) output for an unreachable address:


-> ping "192.0.2.1",1
no answer from 192.0.2.1
value = -1 = 0xffffffff = _end + 0xfff91c4f

23
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

If the first argument uses a host name, ping( ) uses the host table to look it up, as
in the following example:
-> ping "caspian",1
caspian is alive
value = 0 = 0x0

The second argument specifies how many received packets it needs before
terminating. A value of one tells ping( ) to terminate and report success as soon as
the first response packet arrives. A value of zero tells ping( ) to (send and) receive
packets forever or until forcibly terminated). If you specify more than one packet,
ping( ) includes summary statistics. For example, the following test sends packets
to a remote network address until it receives ten acknowledgments. Then the test
reports on the time that it takes to get replies:
-> ping "192.0.2.2",10
PING 192.0.2.2: 56 data bytes
64 bytes from 192.0.2.2: icmp_seq=0. time=176. ms
64 bytes from 192.0.2.2: icmp_seq=1. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=2. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=3. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=4. time=80. ms
64 bytes from 192.0.2.2: icmp_seq=5. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=6. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=7. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=8. time=64. ms
64 bytes from 192.0.2.2: icmp_seq=9. time=64. ms

----192.0.2.2 PING Statistics----


10 packets transmitted, 10 packets received, 0% packet loss
round-trip (ms) min/avg/max = 64/76/176
value = 0 = 0x0

The report format matches that used by the UNIX ping utility. Timings are based
on the system clock, resolution of which could be too coarse to show any elapsed
time when communicating with targets on a local network.
Applications can use ping( ) periodically to test whether another network node is
available. To support this use, the ping( ) routine returns a STATUS value and
accepts a PING_OPT_SILENT flag as a bit in its third argument to suppress printed
output, as in the following code fragment:
/* Check whether other system still there */

if (ping (partnerName, 1, PING_OPT_SILENT) == ERROR)


{
myShutdown(); /* clean up and exit */
}
...

24
2 Configuring VxWorks for the Network Stack
2.4 Testing Connectivity from the Target

You can set one other flag in the third ping( ) argument: PING_OPT_DONTROUTE
restricts ping( ) to hosts that are directly connected, without going through a
gateway. 2

Testing IPv6 Connectivity

The ping6( ) API does not differ much from the ping( ) interface (see the ping6( )
reference entry for the details). Using ping6( ) to test connectivity with a remote
site requires tunneling if the local link does not contain a native IPV6 router. For
information on how to set up a tunnel that links you to a remote IPv6 router, see
20.5 Working with IPv4 and IPv6 Tunneling, p.444.

25
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

26
3
Configuring and Managing
Memory

3.1 Introduction 27
3.2 Configuring VxWorks for Network Memory Pools 28
3.3 Configuring Network Stack Pool Resources 30
3.4 Managing Memory Buffers 39

3.1 Introduction
The Wind River Network Stack uses netBufLib to manage its internal system and
data memory pools. These pools are created automatically if you include the
INCLUDE_NET_POOL component, which also supplies parameters that let you
control the resources allocated to these system and data pools.
This chapter begins by listing the memory management configuration components
discussed in the chapter. Then, it describes how to configure memory pool usage
using the INCLUDE_NET_POOL component and its parameters.
The second part of this chapter covers the buffer management components:
INCLUDE_LINKBUFPOOL, INCLUDE_NETBUFPOOL., INCLUDE_NETBUFLIB, and
the APIs associated with the buffer management libraries, netBufLib and
netBufAdvLib.

27
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

3.2 Configuring VxWorks for Network Memory Pools


The Wind River Network Stack supports the following memory pool and memory
management components:

Network Stack Memory Pool Configuration

linkBufPool

netBufPool

netBufLib

netBufAdvLib
These components are all listed under the
Network Components > Network Core Components folder in Workbench.

Network Stack Memory Pool Configuration

The INCLUDE_NET_POOL component supplies the parameters that you can use to
configure the two memory pools dedicated to the network stack, the system
memory pool and the data memory pool. The system pool provides the network
stack with the memory it needs for its internal structures and data types. The data
pool provides the stack with the memory it needs for packet-oriented data
received from or transmitted over the Internet.
Including INCLUDE_NET_POOL sets up an automatic call to usrNetPoolConfig( ),
which is defined in the configlette net/coreip/usrNetPool.c. The stack initialization
code calls netPoolInit( ) twice, once for the system memory pool, and once for the
data memory pool. The parameters supplied by INCLUDE_NET_POOL provide the
input values to two netPoolInit( ) calls.
The INCLUDE_NET_POOL component requires INCLUDE_NETBUFLIB and
(because the memory pools use the original memory pool back end)
INCLUDE_NETBUFPOOL.
This component contains configuration parameters documented in 3.3.3 Network
Stack Memory Pool Configuration Parameters, p.35.

! WARNING: Failure to correctly configure the system and data memory pools is the
single biggest cause of frozen network applications. The default settings for these
pools are enough to get the stack up, running, and able to respond to simple tests,
such as ping. Deployed applications typically require more resources.

28
3 Configuring and Managing Memory
3.2 Configuring VxWorks for Network Memory Pools

linkBufPool

The INCLUDE_LINKBUFPOOL component pulls in linkBufPool, the network


buffer library that provides a simplified interface to the pool management
3
functionality supplied in netBufLib.
This component also introduces a new pool style optimized and specifically
targeted for network device drivers. This new pool style still relies on tuples of
mBlks clBlks and clusters, but, for pools in the new style, the structures in a single
tuple are now contiguous in memory. In addition, pools in the new style can
borrow buffers from a parent pool. Thus, the pools are not of an absolutely fixed
size. Pools in the new style support a delayed destroy mechanism. This mechanism
waits until all buffers have been returned to the pool before the pool is freed
entirely.
The INCLUDE_LINKBUFPOOL component requires INCLUDE_NETBUFLIB.

netBufPool

The INCLUDE_NETBUFPOOL component pulls in the netBufPool library and


configures the system to automatically set up the network stack’s internal system
and data memory pools. To control the resources allocated to these pools, use the
parameters of the INCLUDE_NET_POOL component.
To select the back end used for a particular net pool, pass a pointer to the back
end's table of routines to the pool creation routine. For the new LINKBUFPOOL
back end, pass the pointer _pLinkPoolFuncTbl, and for the default NETBUFPOOL
back end, pass _pNetPoolFuncTbl.
The INCLUDE_NETBUFPOOL component requires INCLUDE_NETBUFLIB.

netBufLib

The INCLUDE_NETBUFLIB component pulls in netBufLib, the library that


provides the public APIs for managing a memory pool dedicated to
packet-oriented data. Both INCLUDE_LINKBUFPOOL and
INCLUDE_NETBUFPOOL require INCLUDE_NETBUFLIB.
When working with this library, keep in mind that some of the newer APIs in this
library are supported for the _pNetPoolFuncTbl back end only. Since this chapter
was first written, some of the less-used routines in netBufLib have been removed
to their own library, netBufAdvLib.

29
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The INCLUDE_NETBUFLIB component has no component dependencies.

netBufAdvLib

The INCLUDE_NETBUFADVLIB component pulls in netBufAdvLib, the library


that provides additional, less-used routines that used to be in the netBufLib
library. This change was made to improve scalability. The moved routines are:
■ netPoolAttach( ) - attach to the named pool
■ netPoolDetach( ) - detach and decrement usage reference
■ netPoolBind( ) - bind a child pool to a parent netPool, allow resource sharing
■ netPoolUnbind( ) - unbind two pools
■ netTupleListFree( ) - frees a Tuple list to the netPool
■ netTupleListGetv - get a list of mBlk-clBlk-cluster Tuples
■ netTuplePhysAddrMap( ) - translate a Tuple chain's buffers into physical
address
The INCLUDE_NETBUFADVLIB component has no component dependencies.

3.3 Configuring Network Stack Pool Resources


This section describes how you manage the build time configuration of the
network stack’s system memory pool and data memory pool. For details on
network pool structure and usage, see 3.4 Managing Memory Buffers, p.39.

3.3.1 Estimating Memory Pool Usage

To choose values for these parameters, you need to know how much memory your
deployed application will require. Regrettably, there is no simple formula that you
can use to anticipate memory usage. Your only real option is to determine memory
usage empirically. This means running your application under the debugger,
pausing the application at critical points in its execution, and monitoring the state
of the memory pool. You will need to perform these tests under both stressed and
unstressed conditions.

30
3 Configuring and Managing Memory
3.3 Configuring Network Stack Pool Resources

Routines to Use

To determine memory pool usage, use the following routines:



netStackSysPoolShow( ) – show network stack system pool statistics.
3

netStackDataPoolShow( ) – show network stack data pool statistics.

memShow( ) – show blocks and statistics for the current heap partition.
For information on the output of these routines, see the associated reference
entries.

General Factors to Consider

While reliably estimating network pool resource needs requires observing your
network applications in action, there are some general facts of which to be aware.
■ For the most part, the stack allocates bare clusters from the cluster pools of the
stack system pool. Therefore, the system pool does not require large numbers
of mBlks or clBlks.
■ In most cases, received packets are delivered to the stack in tuples loaned from
network driver receive pools. If these packets are forwarded, the loaned tuples
are passed to the outgoing interface and are freed when transmission
completes. Thus, no network stack data pool resources are usually needed in
the forwarding path, or for pure receive traffic; however, the number of
available tuples in these separate driver receive pools may need to be adjusted.
■ Tuples are allocated from the stack data pool by the socket layer when local
applications send data. If zero-copy socket sends are used, the data clusters
themselves are provided by the application, but mBlks and clBlks for these
sends frequently come from the stack data pool. This, when zero-copy socket
sends (for example, zbuf sends) are performed, the stack data pool needs extra
mBlks and clBlks.
■ TCP (and other reliable protocols) keep a copy of sent data in the send socket
buffer until it is acknowledged by the peer. In the socket buffer, application
send data is described as a chain of tuples. TCP constructs mBlk chains
referencing shared clusters and clBlks in these tuples, and passes the
duplicated chain of mBlks to the network interface driver for transmission. To
construct these duplicate mBlk chains, there should be more mBlks in the
network stack data pool than the total number of clusters (which is usually the
same as the total number of clBlks).

31
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


If you are working with SCTP, keep in mind that it uses a 20-byte cluster for
each streaming connection. If you know that your application will use a large
number of such connections, you need to increase the number of 20-byte
clusters allocated in the system memory table.

3.3.2 Mapping Configuration Parameters to netPoolInit( )

The netPoolInit( ) routine is defined in netBufLib as follows:


STATUS netPoolInit
(
NET_POOL_ID pNetPool, /* returns the pool ID */
M_CL_CONFIG * pMclBlkConfig, /* management structure counts */
CL_DESC * pClDescTbl, /* supported buffer sizes */
int clDescTblNumEnt, /* number of supported sizes */
POOL_FUNC * pFuncTbl /* pool function table */
)

The pMclBlkConfig parameter references an M_CL_CONFIG structure, defined as


follows:
typedef struct
{
int mBlkNum; /* number of mBlk structures */
int clBlkNum; /* number of clBlk structures */
char * memArea; /* start of pre allocated memory area */
int memSize; /* size of pre allocated memory area */
} M_CL_CONFIG;

All four fields of this structure map to parameters in INCLUDE_NET_POOL. For a


list of the parameters, see 3.3.3 Network Stack Memory Pool Configuration Parameters,
p.35.

Table 3-1 Mapping of M_CL_CONFIG Fields to System and Data Pool Configuration Parameters

M_CL_CONFIG Field System Pool Parameter Data Pool Parameter

mBlkNum NUM_SYS_MBLKS NUM_DAT_MBLKS

clBlkNum NUM_SYS_CLBLKS NUM_DAT_CLBLKS

memArea PMA_SYSPOOL PMA_DATPOOL

memSize PMS_SYSPOOL PMS_DATPOOL

The _MBLKS and _CLBLKS configuration parameters determine the number of


mBlk and clBlk structures allocated to manage the data (clusters).

32
3 Configuring and Managing Memory
3.3 Configuring Network Stack Pool Resources

NOTE: For most purposes, every cluster buffer in a memory pool requires exactly
one clBlk structure. The exception to this occurs when code uses unchained
unshared cluster buffers directly, as is often the case for the stack system pool.
Every clBlk structure requires at least one mBlk structure, but buffer sharing 3
(copying by reference) increases your mBlk needs. If you do not already
understand the relationship between the mBlk, the clBlk, and the cluster, see
3.4 Managing Memory Buffers, p.39.

The PMA_ and PMS_ parameters let you handle the allocation of the memory that
contains the memory pool management structures and data. If you do not need to
control the exact memory location of these structures and data, you can leave the
PMA_ and PMS_ parameters at their default value of zero. This tells the network
stack initialization code to handle the allocation.
The pClDescTbl parameter in netPoolInit( ) points to the start of a table of CL_DESC
structures. A CL_DESC structure is defined as:
typedef struct clDesc
{
int clSize; /* cluster size */
int clNum; /* number of clusters */
char * memArea; /* start of pre-allocated memory area */
int memSize; /* size of pre-allocated memory area */
} CL_DESC;

For the system pool, each of the fields in this structure gives rise to a configuration
parameter. Thus, each CL_DESC gives rise to four configuration parameters for
each buffer size supported in the system pool. The system buffer pool supports 8
different buffer sizes, which gives rise to the configuration parameters listed in
Table 3-2.
Of the parameters listed in Table 3-2, the only ones you are likely to change are the
NUM_ parameters. These parameters specify the number of clusters in the pool.
You will need to increase the parameter values to values appropriate to your
deployed application. The PMA_ and PMS_ parameters let you handle the memory
allocation for the data clusters. If you leave these parameters at their default value
of zero, the network stack initialization code handles the memory allocation for
you.

! WARNING: Do not change the SIZ_ parameter values casually. Change them only
if a careful study of the output of netStackSysPoolShow( ),
netStackDataPoolShow( ), and memShow( ) indicates that you need to increase
these values to handle the demands placed on the stack by the application you
intend to deploy.

33
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 3-2 Mapping of CL_DESC Fields to System Pool Configuration Parameters

clSize clNum memArea memSize

SIZ_SYS_16 NUM_SYS_16 PMA_SYS_16 PMS_SYS_16

SIZ_SYS_32 NUM_SYS_32 PMA_SYS_32 PMS_SYS_32

SIZ_SYS_64 NUM_SYS_64 PMA_SYS_64 PMS_SYS_64

SIZ_SYS_128 NUM_SYS_128 PMA_SYS_128 PMS_SYS_128

SIZ_SYS_256 NUM_SYS_256 PMA_SYS_256 PMS_SYS_256

SIZ_SYS_512 NUM_SYS_512 PMA_SYS_512 PMS_SYS_512

SIZ_SYS_1024 NUM_SYS_1024 PMA_SYS_1024 PMS_SYS_1024

SIZ_SYS_2048 NUM_SYS_2048 PMA_SYS_2048 PMS_SYS_2048

The network stack requires 8 buffer sizes to allocate memory for the data
structures that it uses internally. These buffer sizes (in bytes) are presently 20, 44,
96, 172, 292, 664, 1144, and 2048 bytes and correspond to the SIZ_SYS_16,
SIZ_SYS_32, SIZ_SYS_64 parameters and so on. These default sizes are based on a
compromise between the various data structure sizes needed internally and the
distribution of sizes that netBufLib can support within a single memory pool. As
such, the exact sizes may change in the future as the sizes of stack data structures
are modified.
Each supported buffer size within a netBufLib pool must be unique within a size
range that is bounded by powers of two. The bottom power of two is included in
the range. The upper power of two is in the next range. Thus, SIZ_SYS_16 indicates
the range of sizes from 16 to 31 bytes. A buffer size of 20 bytes is valid within this
range. Likewise, 44 (SIZ_SYS_32) is within the 32 to 63 size range, 96 (SIZ_SYS_64)
is within the 64 to 127 size range, and so on. When the stack needs memory for any
structure or data type of 20 bytes or less, the stack takes a SIZ_SYS_16 buffer. When
it needs a buffer of more than 20 bytes but less than 45 bytes, it takes a SIZ_SYS_32
buffer, and so on for other buffer sizes up to 2048.
For the data pool, the stack uses buffer sizes that were chosen based on the packet
data exchanged on the Internet. Currently, these sizes are hard-coded to 64, 128,
256, 512, 1024, and 2048. This requires six CL_DESC structures. Because the cluster
size is hard coded, each CL_DESC structure gives rise to only three (not four)
configuration parameters, which are listed in Table 3-3.

34
3 Configuring and Managing Memory
3.3 Configuring Network Stack Pool Resources

Table 3-3 Mapping of CL_DESC Fields to Data Pool Configuration Parameters

clSize clNum memArea memSize

hard coded to 64 NUM_DAT_64 PMA_DAT_64 PMS_DAT_64 3

hard coded to 128 NUM_DAT_128 PMA_DAT_128 PMS_DAT_128

hard coded to 256 NUM_DAT_256 PMA_DAT_256 PMS_DAT_256

hard coded to 512 NUM_DAT_512 PMA_DAT_512 PMS_DAT_512

hard coded to 1024 NUM_DAT_1024 PMA_DAT_1024 PMS_DAT_1024

hard coded to 2048 NUM_DAT_2048 PMA_DAT_2048 PMS_DAT_2048

hard coded to 4096 NUM_DAT_4096 PMA_DAT_4096 PMS_DAT_4096

hard coded to 8192 NUM_DAT_8192 PMA_DAT_8192 PMS_DAT_8192

hard coded to 16384 NUM_DAT_16384 PMA_DAT_16384 PMS_DAT_16384

hard coded to 32768 NUM_DAT_32768 PMA_DAT_32768 PMS_DAT_32768

hard coded to 65536 NUM_DAT_65536 PMA_DAT_65536 PMS_DAT_65536

Of the parameters listed in Table 3-3, the only ones you are likely to change are the
NUM_ parameters. These parameters specify the number of clusters in the pool.
You will need to increase to values appropriate to your deployed application. The
PMA_ and PMS_ parameters let you handle the memory allocation for the data
clusters. If you leave these parameters at their default value of zero, the network
stack initialization code handles the memory allocation for you.

3.3.3 Network Stack Memory Pool Configuration Parameters

Following are tables listing the configuration parameters associated with the
INCLUDE_NET_POOL component.

NUM_SYS_MBLKS

Synopsis: The number of mBlk structures needed for the system pool.
Default: 20

35
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NUM_SYS_CLBLKS

Synopsis: The number of clBlk structures needed for the system pool.
Default: 20

PMA_SYSPOOL

Synopsis: Start of preallocated space for system pool management buffers.


Default: 0
This is an optional parameter. If you leave it at the default value of zero, the
stack initialization code allocates the necessary memory.

PMS_SYSPOOL

Synopsis: Size of preallocated space for system pool management buffers.


Default: 0
This is an optional parameter. If you leave it at the default value of zero, the
stack initialization code allocates the necessary memory.

SIZ_SYS_16

Synopsis: The buffer size selected from within this size band, 16 to 31 bytes.
Default: 20

! WARNING: Do not change the SIZ_ parameter values casually. Change them only
if a careful study of the output of memShow( ), netStackSysPoolShow( ), and
netStackDataPoolShow( ) indicates that you need to increase these values to
handle the demands placed on the stack by the application you intend to deploy.

The netBufLib implementation for memory pools that support multiple buffer
sizes requires that each supported buffer size be unique within a size range
that is bounded by powers of two. The bottom power of two is included in the
range. The upper power of two is in the next range.
SIZ_SYS_32 indicates the band of sizes from 32 to 63 bytes.
SIZ_SYS_64 indicates the band of sizes from 64 to 127 bytes.
SIZ_SYS_128 indicates the band of sizes from 128 to 255 bytes.
SIZ_SYS_256 indicates the band of sizes from 256 to 511 bytes.
SIZ_SYS_512 indicates the band of sizes from 512 to 1023 bytes.
SIZ_SYS_1024 indicates the band of sizes from 1024 to 2047 bytes.
SIZ_SYS_2048 indicates the band of sizes from 2048 to 4095 bytes.

36
3 Configuring and Managing Memory
3.3 Configuring Network Stack Pool Resources

The selected buffer sizes for the size bands SIZ_SYS_32 through SIZ_SYS_2048
are as follows:
SIZ_SYS_32 44
SIZ_SYS_64 96 3
SIZ_SYS_128 172
SIZ_SYS_256 292
SIZ_SYS_512 664
SIZ_SYS_1024 1144
SIZ_SYS_2048 2048

NUM_SYS_16

Synopsis: A count of the buffers in the SIZ_SYS_16 size band.


Default: 250
NUM_SYS_32 through NUM_SYS_2048 parallel the description shown above.
The default values are as follows:
NUM_SYS_32 200
NUM_SYS_64 100
NUM_SYS_128 150
NUM_SYS_256 100
NUM_SYS_512 50
NUM_SYS_1024 30
NUM_SYS_2048 5

PMA_SYS_16

Synopsis: Start of preallocated space for buffers in the SIZ_SYS_16 band.


Default: 0
PMA_SYS_32 through PMA_SYS_2048 parallel the description shown above but
deal with their respective buffer size bands. PMA_SYS_16 through
PMA_SYS_2048 are optional parameters. If you leave them at the default value
of zero, the stack initialization code allocates the necessary memory.

PMS_SYS_16

Synopsis: Size of preallocated space for buffers in the SIZ_SYS_16 band.


Default: 0
PMS_SYS_32 through PMS_SYS_2048 parallel the description shown above but
deal with their respective buffer size bands. PMS_SYS_32 through

37
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

PMS_SYS_2048 are optional parameters. If you leave them at the default value
of zero, the stack initialization code allocates the memory.

NUM_DAT_MBLKS

Synopsis: The number of mBlk structures needed for the data pool.
Default: NUM_DAT_CLBLKS

NUM_DAT_CLBLKS

Synopsis: The number of clBlk structures needed for the data pool.
Default: NUM_DAT_64 + NUM_DAT_128 + NUM_DAT_256 + NUM_DAT_512 +
NUM_DAT_1024 + NUM_DAT_2048 + NUM_DAT_4096 +
NUM_DAT_8192 + NUM_DAT_16384 + NUM_DAT_32768 +
NUM_DAT_65536

NUM_DAT_64

Synopsis: A count of the 64-byte buffers in the data memory pool.


Default: 100
NUM_DAT_128 through NUM_DAT_65536 parallel the description shown
above. However, the default values are as follows:
NUM_DAT_128 400
NUM_DAT_256 40
NUM_DAT_512 40
NUM_DAT_1024 25
NUM_DAT_2048 50
NUM_DAT_{4096, 8192, 16384, 32768, 65536 } all have a default value of 0 (zero).

PMA_DAT_64

Synopsis: Start of preallocated space for the 64-byte data pool buffers.
Default: 0
PMA_DAT_128 through PMA_DAT_65536 parallel the description shown above
but deal with 128-byte buffers, 256-byte buffers, 512-byte buffers, 1024-byte
buffers, and 2048-byte buffers respectively. PMS_DAT_64 through
PMS_DAT_65536 are optional parameters. If you leave them at the default
value of zero, the stack initialization code allocates the necessary memory.

38
3 Configuring and Managing Memory
3.4 Managing Memory Buffers

PMS_DAT_64

Synopsis: Size of preallocated space for the 64-byte data pool buffers.
Default: 0
3
This is an optional parameter. If you leave it at the default value of zero, the
stack initialization code allocates the necessary memory. PMS_DAT_128
through PMS_DAT_65536 parallel the description shown above but deal with
128-byte buffers, 256-byte buffers, 512-byte buffers, 1024-byte buffers, and
2048-byte buffers respectively.

3.4 Managing Memory Buffers


The netBufLib library is pulled into the VxWorks image by including the
INCLUDE_NETBUFLIB component, described in netBufLib, p.29. Using netBufLib,
you can set up a memory pool that stores its data in buffers known as clusters. To
manage these data clusters, netBufLib relies upon structures called mBlks and
clBlks. These management structures provide support for features such a buffer
loaning and buffer chaining.
The current netBufLib implementation supports two different APIs for the
creation of a memory pool. The pools created by these different APIs are not equal
in functionality. Pools created through the original netPoolInit( ) API are limited
to functionality supported in the original netBufLib implementation. Pools
created through the new netPoolCreate( ) API use an improved management
scheme that allows for:

allowing a child pool to borrow buffers from a parent pool

delaying pool deletion until all buffers are returned
Back end pool management routines handle the low-level aspects of managing the
memory in the pool. Typically, you do not call these back end routines directly.
Instead, you call the higher-level netBufLib routines when you need to work with
the buffers in the pool.

39
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

3.4.1 Understanding How netBufLib Pool Organizes Memory

The memory in a netBufLib memory pool is organized using mBlk structures,


clBlk structures, and cluster buffers. The mBlk and clBlk structures store the
information needed to support buffer loaning and buffer chaining for the data that
is stored in a cluster. When requesting a buffer from a memory pool, you get a
tuple consisting of an mBlk, a clBlk, and a cluster.

Clusters

Valid cluster sizes range up to 64KB (65536 bytes). The netBufPool back end
supports multiple clusters sizes, but requires that only one cluster size is allowed
between consecutive powers of two. The linkBufPool back end allows, at most, a
single cluster size within each net pool.

mBlks and clBlks

To support buffer (cluster) loaning, netBufLib tracks clusters using mBlk and
clBlk structures.
For each cluster in a memory pool, there needs to be a corresponding clBlk
structure.
The clBlk structure tracks how many mBlks share its underlying cluster. Above
the clBlk, is the mBlk structure. This structure stores a link to a clBlk and can store
a link to another mBlk. By chaining mBlks, you can reference an arbitrarily large
amount of data, such as a packet chain (see Figure 3-1).
The mBlk structure is the primary object you use to access the data that resides in
a memory pool. Because an mBlk is only a reference to the data available through
a clBlk, network layers can exchange data without copying between internal
buffers. Each mBlk structure stores separate links for the data within a packet and
for the data that starts a new packet.

40
3 Configuring and Managing Memory
3.4 Managing Memory Buffers

Figure 3-1 Presentation of Two Packets in One mBlk Chain

mBlk mBlk mBlk null


3

clBlk clBlk clBlk


Packet 1

Cluster Cluster Cluster


64 bytes 512 2048
bytes bytes

mBlk mBlk null

clBlk clBlk
Packet 2

Cluster Cluster
64 bytes 2048
bytes

Because the mBlk references the cluster data through a clBlk, duplicating an mBlk
need not copy the cluster data. For example, mBlk A in Figure 3-2 is a duplicate of
mBlk 1. Creating this duplicate did not require the copying of the underlying
cluster. The duplication did require incrementing the external reference count
stored in the clBlk that manages the underlying cluster. This is critical when it
comes time to free an mBlk.
If you use netBufLib to free the mBlk, the mBlk is freed back to the pool and the
reference count in the underlying clBlk is decremented. If this reference count
drops to zero (indicating that no mBlks are referencing the cluster), the clBlk and
cluster are also freed back to the memory pool.

41
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Figure 3-2 Different mBlks Can Share the Same Cluster

mBlk 1 mBlk 2 null

mBlk A mBlkBb
mBlk null

clBlk clBlk

Cluster Cluster
64 bytes 2048
bytes

3.4.2 Working with the New Memory Pool API

When using the older netPoolInit( ) API, you preallocate distinct memory areas
for the mBlk structures, the clBlk structures, and for each cluster size supported
in the memory pool. Using the newer netPoolCreate( ) API, this preallocation is
not necessary. The netPoolCreate( ) call allocates memory internally for the
management and data structures required in the pool.

NOTE: The _pLinkBufPool back end creates pools limited to a single buffer size.

Creating a Memory Pool

To create a memory pool, use netPoolCreate( ):


NET_POOL_ID netPoolCreate
(
NETBUF_CFG * pNetBufCfg, /* Configuration Structure */
POOL_FUNC * pFuncTbl /* Optional plug in function table */
)

As input, netPoolCreate( ) requires only pNetBufCfg (the pFuncTbl parameter is


optional, see About the pFuncTbl Parameter in a netPoolCreate( ) Call, p.44).

42
3 Configuring and Managing Memory
3.4 Managing Memory Buffers

The pNetBufCfg parameter passes in a pointer to a populated NETBUF_CFG


structure:
typedef struct netBufCfg
{ 3
char * pName; /*
Pool Name */
UINT32 attributes; /*
pool attributes */
void * pDomain; /*
RTP ID or NULL for kernel */
int ctrlNumber; /*
# of ctrl structures to pre-allocate */
PART_ID ctrlPartId; /*
Mem Partition for Control structures */
/*
NULL = use Kernel partition */
int bMemExtraSize; /*
Additional memory for runtime buffers */
PART_ID bMemPartId; /*
Mem Partition for buffers */
/*
NULL = default for kernel or RTP */
NETBUF_CL_DESC * pClDescTbl; /* desired cluster sizes and count */
int clDescTblNumEnt; /* num of entries in cluster table */
} NETBUF_CFG;

The pClDescTbl field of the above structure points to an array of


NETBUF_CL_DESC structures:
typedef struct netBufClDesc
{
int clSize; /* Cluster Size */
int clNum; /* Number of clusters in pool */
} NETBUF_CL_DESC;

These structures are defined in netBufLib.h. Using these structures, you can
specify the pool name, its attributes (see Table 3-4), whether it is allocated out of
the kernel memory space or an RTP, the number of mBlks and clBlks (ctrlNumber
of each), and the numbers and sizes of the clusters available from the pool. The
allocation of the required space is handled for you internally by netPoolCreate( ).
For more information, see the netPoolCreate( ) reference entry.

Table 3-4 Pool Attributes

Attribute Attribute Description

ATTR_AI_SH_ISR Integer aligned, Sharable, ISR Safe


ATTR_AC_SH_ISR Cache line aligned, Sharable, ISR Safe

ATTR_AP_SH_ISR Page aligned, Sharable, ISR Safe


ATTR_AI_ISR Integer aligned, Private, ISR Safe
ATTR_AC_ISR Cache line aligned, Private, ISR Safe
ATTR_AP_ISR Page aligned, Private, ISR Safe

43
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Attaching to a Memory Pool

Attaching to a memory pool allows a task to use the buffers in the pool. This
routine lets multiple agents share a preexisting pool.
For example, all of the network interfaces managed by a driver (or even by
multiple drivers) could share a single pool. The netPoolAttach( ) checks that the
pool is intended to be sharable and guards against pool release at least until one
calls netPoolDetach( ). For more information on attaching and detaching from a
memory pool, see the netPoolAttach( ) and netPoolDetach( ) reference entries.

Binding to a “Parent” Memory Pool

Anticipating the demand on a pool can be difficult. In addition, if the demand is


inconsistent, it can be inefficient to size the memory pool to its peak use. Using the
netPoolCreate( )-style memory pool, it is possible to bind to a parent pool from
which the child pool can borrow buffers at need. When the borrowed buffer is
freed, it is freed back to the parent pool. The child pool does not retain the
borrowed buffer.
For more information on binding to (or unbinding from) a parent memory pool,
see the netPoolBind( ) and netPoolUnbind( ) reference entries.

Safely Releasing a Pool

To free a pool created by the netPoolCreate( ) API, call netPoolRelease( ). This


routine puts a pool into a release state. After all buffers have been returned to the
pool, the pool is automatically destroyed.

Retrieving the ID or Name of a Pool

To retrieve the ID or name of a pool, use netPoolIdGet( ) and netPoolNameGet( ).

About the pFuncTbl Parameter in a netPoolCreate( ) Call

Using the pFuncTbl parameter, you can specify an alternative set of back end buffer
management routines for the network pool. The INCLUDE_NETBUFPOOL back
end supplies the _pNetPoolFuncTbl table. The INCLUDE_LINKBUFPOOL back
end provides the _pLinkPoolFuncTbl table.

44
3 Configuring and Managing Memory
3.4 Managing Memory Buffers

3.4.3 Working with the Original Memory Pool API

The original netBufLib API for creating a memory pool is netPoolInit( ). Pools
created through netPoolInit( ) do not support:
3

borrowing buffers from a parent pool

delaying pool deletion until all buffers are returned

Setting Up a Memory Pool in the Original Style

Setting up an original-style memory pool culminates in a call to netPoolInit( ).


Before calling netPoolInit( ), you must have allocated all the memory you want to
include in the pool. You then reference that memory in the CL_DESC and
M_CL_CONFIG structures that you submit to netPoolInit( ). The CL_DESC and
M_CL_CONFIG structures supply netPoolInit( ) with the memory pointers,
structure counts, buffer sizes, and buffer counts that define the memory pool.

M_CL_CONFIG

An M_CL_CONFIG structure specifies the pool’s clBlk count, its mBlk count, and
a previously allocated memory area identified by a starting address and a size. The
count values are analogous to the NUM_SYS_MBLKS and NET_SYS_CLBLKS
values you specified for the network system memory table.
Unless the pool is primarily used to allocate bare clusters, the clBlk count you
specify is usually equal to the number of clusters in the memory pool. The mBlk
count would usually be at least as large, but could be larger or smaller depending
on how you use the memory pool. The allocated memory referenced in the
supplied pointer should be large enough to contain all the clBlk and mBlk
structures specified by the supplied counts.

CL_DESC

Each row of a table of CL_DESC structures associates a cluster size with a cluster
count and a memory area identified by a starting address and a size. If you are
setting up a table of CL_DESC structures for a network driver pool, your table will
likely need only one row. This row specifies a cluster size close to the MTU of the
underlying device. For example, the Lance Ethernet driver uses a cluster size of
1520 bytes, which is the Ethernet MTU plus some slack. The CL_DESC table for a
network protocol will likely contain several rows. This is because protocols
typically require buffers of several different sizes.

45
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

When deciding on cluster sizes, keep in mind that a table of CL_DESC structures
requires each size to be unique within a size range that is bounded by powers of
two. The bottom power of two is within the range, and the upper power of two is
in the next range.
Figure 3-3 shows two examples of sets of cluster sizes. The first, {48, 92, 244}, is
valid because there is at least one power of two between the different sizes. The
second, {48, 88, 128, 192}, is invalid because the cluster sizes of 128 and 192 both fall
within the range bounded by 128 and 256.

Figure 3-3 Choosing Correct Cluster Sizes

{ 48 92 244 } This set is correctly chosen so that


only one size lies between two
adjacent powers of two.
32 64 128 256 512

{ 48 88 128 192 } This set is not valid. The cluster sizes


of 128 and 192 fall in the same range.

In addition, although the {48, 92, 244} set of cluster sizes does not skip a size band,
netBufLib does allow this. Thus, {48, 244} would be a valid set of cluster sizes for
a single memory pool. When setting up a table of CL_DESC structures, make sure
that you specify the smaller buffer sizes first. Ordering the sizes from smaller to
larger is a requirement.

Storing and Using Data in Clusters

When your driver or protocol needs a buffer for a packet, allocate an mBlk tuple
from the pool using netTupleGet( ). If your protocol needs to allocate a control
structure not containing packet data, it can allocate a bare cluster using
netClusterGet( ) or the clusterGet( ) macro, rather than allocating a tuple. When
doing so, it can determine the appropriate cluster pool to use by calling
netClPoolIdGet( ) or the clPoolIdGet( ) macro. Sometimes this can be done ahead
of time.

46
3 Configuring and Managing Memory
3.4 Managing Memory Buffers

NOTE: The various net*Get( ) routines reserve memory from a pre-allocated pool.
Internally, they are non-blocking, and are safe to call from interrupt level,
provided the M_DONTWAIT option is used rather than M_WAIT. This avoids
calling the protocol garbage collection routines if the allocation is not immediately 3
successful.
Generally the net*Free( ) routines (specifically those which involve freeing cluster
blocks) should not be called from interrupt level, because a user-specified cluster
free routine might be present and unsafe to call from an ISR. In particular, END
drivers should avoid freeing transmit M_BLK chains at interrupt level.

Protocols prepending headers to application data may use the mBlk chaining
feature to do so, although if space is reserved for headers at the start of the data
cluster, this can be more efficient. Various routines are provided in netBufLib for
copying or sharing data in mBlk chains. For example, to read the data out of an
mBlk chain and into a buffer, call netMblkToBufCopy( ). Use
netMblkChainDup( ) to form a new mBlk chain sharing data with part of an
existing chain.

Freeing mBlks, clBlks, and Clusters

To return chain of tuples (linked by the mBlkHdr.mNext field) to the


memory pool, call netMblkClChainFree( ). This frees all mBlks in the
chain back to the pool. It also decrements the reference counters in all the clBlks in
the chain. If the reference counter for a clBlk drops to zero, that clBlk and its
associated cluster are also freed back to the pool. To free a single
mBlk/clBlk/cluster back to the memory pool, use netMblkClFree( ).

3.4.4 Using Macros for Buffer Manipulation

M_PREPEND( m, plen, how )

This macro prepends plen bytes at the beginning of buffer m. You can set how to
M_WAIT or M_DONTWAIT. This corresponds to the canWait parameter in the
netMblkGet( ) call. It specifies the desired behavior if there is not enough space in
m for plen bytes and a new buffer must be allocated and added to the buffer chain
to contain these prepended bytes.
For information on pre-allocating space at the beginning of a buffer, which
increases the speed of the M_PREPEND( ) operation, see 21.4.3 Early Link-Level
Header Allocation in an NPT Driver, p.465.

47
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

M_ALIGN( m, len )

This macro adjusts the data pointer of newly allocated tuple’s M_BLK, m, to point
to an address len bytes before the end of the tuple’s cluster, rounded down to a
four-byte boundary. It is only valid to call this macro when the data pointer of m
points to the start of the tuple cluster, for instance right after tuple allocation. Note
that M_ALIGN( ) does not append space to what is already reserved in the M_BLK.

M_LEADINGSPACE( m )

This macro reports the size of the leading space that comes before the data held in
the cluster belonging to buffer m. M_LEADINGSPACE returns zero if the tuple's
cluster is shared (that is, if the cluster reference count is not 1).

M_TRAILINGSPACE( m )

For the cluster belonging to mbuf m, this macro computes the amount of remaining
space past the segment of the cluster presently described by m.
M_TRAILINGSPACE returns zero if the tuple's cluster is shared (that is, if the
cluster reference count is not 1).

48
4
Modifying Parameters
at Run-time

4.1 Introduction 50
4.2 kern.ipc Variables 50
4.3 net.inet.icmp Variables 51
4.4 net.inet.ip Variables 52
4.5 net.inet.ip.portrange Variables 54
4.6 net.inet.raw Variables 55
4.7 net.inet.sctp Variables 55
4.8 net.inet.tcp Variables 58
4.9 net.inet.tcp.syncache Variables 62
4.10 net.inet.udp Variables 62
4.11 net.inet6.icmp6 Variables 63
4.12 net.inet6.ip6 Variables 65
4.13 net.link.ether.inet Variables 68

49
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

4.1 Introduction
This chapter describes the network stack configuration variables that you can set
or inspect at run-time by calling Sysctl( ) or sysctl( ). Many of these variables
receive their default value from parameters of build-time configuration
components. For information on Sysctl( ) or sysctl( ), see their reference entries.

4.2 kern.ipc Variables


kern.ipc.max_hdr

Sets a stack parameter whose default value is the sum of the MAX_LINKHDR_CFG
(maximum size of a link header) and MAX_PROTOHDR_CFG (maximum size of a
protocol header) configuration parameters.

kern.ipc.max_linkhdr

Specifies the maximum size of a link header. Use this variable to reset the current
value of the MAX_LINKHDR_CFG configuration parameter.

kern.ipc.max_protohdr

Specifies the maximum size of a protocol header. Use this variable to reset the
current value of the MAX_PROTOHDR_CFG configuration parameter.

kern.ipc.maxsockbuf

Sepcifies the maximum socket buffer size. Use this variable to reset the current
value of the MAXSOCKBUF_CFG configuration parameter.

kern.ipc.sockbuf_waste_factor

Specifies the sb_efficiency value for sbreserve( ) calls. The stack reserves the
specified number of buffers for each new socket. Use this variable to reset the
current value of the SOCKBUF_WASTE_FACTOR_CFG configuration parameter.

kern.ipc.somaxconn

Specifies the maximum pending socket connections queue size. Use this variable
to reset the current value of the SOMAXCONN_CFG configuration parameter.

50
4 Modifying Parameters at Run-time
4.3 net.inet.icmp Variables

4.3 net.inet.icmp Variables


net.inet.icmp.bmcastecho

If TRUE, enables ICMP broadcast echo. Use this variable to reset the current value
of the ICMPBMCASTECHO_CFG configuration parameter. 4

net.inet.icmp.drop_redirect

If TRUE, tells stack to drop incoming ICMP redirect packets. Use this variable to
reset the current value of the ICMP_DROP_REDIRECT_CFG configuration
parameter.

net.inet.icmp.icmpErrorLen

Tells the system the expected size of the payload in an ICMP error message. Use
this variable to reset the current value of the ICMPERRORLEN_CFG configuration
parameter.
The ICMP error message payload consists of an ICMP message header followed by
a sample from the start of the bad packet that triggered the ICMP error. The ICMP
error message header requires 8 bytes. At one time, a sample of 8 bytes from the
bad packet was considered sufficient. With the advent of IP tunneling and other
technologies, this message sample was found to be insufficient.
A sample of 56 bytes has proven to be adequate for most tunneled messages. Thus,
the default is 64 bytes, which allows 8 bytes for the ICMP header plus 56 for the
sample of the bad packet. If you find that you need a larger sample of the bad
packet, increase icmpErrorLen to any value not greater than 488 bytes. This upper
limit is imposed by the maximum size of an ICMP datagram.

NOTE: When working with the protocolcltinput( ) routines, such as pfctlinput( ) or


the routines it calls, the sockaddr structure used to report the error message is
actually an icmp_info structure that has been cast as a sockaddr structure. The
icmp_info structure, defined in ip_icmp.h is a sockaddr_in structure that has been
extended to include a new field, errorPktLen. This field reports the length of the
bad IP packet. For all non-ICMP error messages, the value of this field is zero.
If this extra information is not of interest to you, you can ignore it and continue
dealing with the ICMP error message as a sockaddr structure or sockaddr_in
structure. When working with ICMP error messages for tunnelled packets, this
length information can be convenient.

51
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet.icmp.icmplim

Sets the ICMP error-response bandwidth limit. Use this variable to reset the
current value of the ICMPLIM_CFG configuration parameter.

net.inet.icmp.icmplim_output

If TRUE, the default, this parameter tells the stack to print a message informing you
that the bandwidth, (icmplim) is exceeded.

net.inet.icmp.log_redirect

If TRUE, tells the stack to log ICMP redirects of incoming packets. Use this variable
to reset the current value of the ICMP_LOG_REDIRECT_CFG configuration
parameter.

net.inet.icmp.maskrepl

Accept incoming ICMP mask reply packets. Use this variable to reset the current
value of the ICMPMASKREPL_CFG configuration parameter.

net.inet.icmp.stats

Lists ICMP statistics.

4.4 net.inet.ip Variables


net.inet.ip.accept_sourceroute

If TRUE, enables accepting source-routed IP packets. Use this variable to override


the IP_ACCEPTSOURCEROUTE_CFG configuration parameter.

net.inet.ip.check_interface

If TRUE, enables verification of whether a packet arrived on the correct interface.


Use this variable to reset the current value of the IP_CHECKINTERFACE_CFG,
which is set in INCLUDE_IPV4.

52
4 Modifying Parameters at Run-time
4.4 net.inet.ip Variables

net.inet.ip.fastforwarding

If TRUE, enables flow-based IP forwarding. Use this variable to reset the current
value of the FASTFORWARDING_CFG configuration parameter.

net.inet.ip.forwarding
4
If TRUE, this variable enables IP forwarding between interfaces. Use this variable
to reset the current value of the IPFORWARDING_CFG configuration parameter.

net.inet.ip.maxfragpackets

Maximum number of IPv4 fragment reassembly queue entries.

net.inet.ip.maxfragsperpacket

Maximum number of fragments per packet.

net.inet.ip.redirect

If TRUE, sending IP redirects is enabled. Use this variable to reset the current value
of the IPSENDREDIRECTS_CFG configuration parameter.

net.inet.ip.rtexpire

Sets the expiration time on dynamically learned routes. Use this variable to reset
the current value of the RTEXPIRE_CFG configuration parameter.

net.inet.ip.rtmaxcache

Sets the upper limit on dynamically learned routes. Use this variable to reset the
current value of the RTMAXCACHE_CFG configuration parameter.

net.inet.ip.rtminexpire

Sets the minimum time to try to hold onto dynamically learned routes. Use this
variable to reset the current value of the RTMINEXPIRE_CFG configuration
parameter.

net.inet.ip.sourceroute

If TRUE, enables forwarding source-routed IP packets. Use this variable to reset the
current value of the IP_DOSOURCEROUTE_CFG configuration parameter.

53
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet.ip.subnets_are_local

If TRUE, tells the stack to test that the in_localaddr for a packet includes other
subnets of the local net. Use this variable to reset the current value of the
SUBNETS_ARE_LOCAL_CFG configuration parameter.

net.inet.ip.ttl

Sets the maximum TTL on IP packets. Use this variable to reset the current value
of the IP_DEFTTL_CFG configuration parameter.

net.inet.ip.stats

Lists IP statistics.

4.5 net.inet.ip.portrange Variables


net.inet.ip.portrange.first

Sets the value of ipport_firstauto, the IP privileged port range. Use this variable to
reset the current value of the IPPORT_RESERVED_CFG configuration parameter.

net.inet.ip.portrange.hifirst

Sets the value of ipport_hifirstauto, the first local port. Use this variable to reset
the current value of the IPPORT_HIFIRSTAUTO_CFG configuration parameter.

net.inet.ip.portrange.hilast

Sets the value of ipport_hilastauto, the last local port. Use this variable to reset the
current value of the IPPORT_HILASTAUTO_CFG configuration parameter.

net.inet.ip.portrange.last

Sets the value of ipport_lastauto, the IP system reserved first port. Use this
variable to reset the current value of the IPPORT_USERRESERVED_CFG
configuration parameter.

54
4 Modifying Parameters at Run-time
4.6 net.inet.raw Variables

net.inet.ip.portrange.lowfirst

Sets the value of ipport_lowfirstauto, whose default value is


IPPORT_RESERVED_CFG minus one.

net.inet.ip.portrange.lowlast
4
Sets the value of ipport_lowlastauto, the IP privileged first port. Use this variable
to reset the current value of the IPPORT_RESERVEDSTART_CFG configuration
parameter.

4.6 net.inet.raw Variables


net.inet.raw.maxdgram

Sets the maximum outgoing raw IP datagram size. Use this variable to reset the
current value of the RAW_MAXDGRAM_CFG configuration parameter.

net.inet.raw.pcblist

List of active raw IP sockets.

net.inet.raw.recvspace

Sets the maximum incoming raw IP datagram size. Use this variable to reset the
current value of the RAW_RECVSPACE_CFG configuration parameter.

4.7 net.inet.sctp Variables


net.inet.sctp.maxdgram

Size, in bytes, of the socket send buffer.

net.inet.sctp.recvspace

Size, in bytes, of the receive buffer.

55
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet.sctp.auto_asconf

Enable auto-ASCONF.

net.inet.sctp.ecn_enable

If TRUE, enable ECN.

net.inet.sctp.ecn_nonce

If TRUE, enable ECN Nonce.

net.inet.sctp.strict_sacks

Default value for the delayed SACK timer.

net.inet.sctp.loopback_nocsum

If TRUE, disable checksum on loopback. That is, do not compute/validate


checksum on packets that go through the loopback.

net.inet.sctp.strict_init

If TRUE, enable strict INIT/INIT-ACK singleton enforcement.

net.inet.sctp.peer_chkoh

Amount to debit receive window of peer per chunk sent.

net.inet.sctp.maxburst

Default maximum burst for SCTP endpoints.

net.inet.sctp.maxchunks

Default maximum chunks on queue per association.

net.inet.sctp.delayed_sack_time

Default delayed SACK timer.

net.inet.sctp.heartbeat_interval

Default heartbeat interval in milliseconds.

net.inet.sctp.pmtu_raise_time

The time, in seconds, to wait before trying to increase PMTU again.

56
4 Modifying Parameters at Run-time
4.7 net.inet.sctp Variables

net.inet.sctp.shutdown_guard_time

Default shutdown guard timer in seconds.

net.inet.sctp.secret_lifetime

Default secret lifetime in seconds. 4

net.inet.sctp.rto_max

Maximum allowable value for retransmission timeout in milliseconds.

net.inet.sctp.rto_min

Minimum allowable value for retransmission timeout in milliseconds.

net.inet.sctp.rto_initial

Initial retransmission timeout in milliseconds.

net.inet.sctp.init_rto_max

Maximum number of retransmission for INIT chunks.

net.inet.sctp.valid_cookie_life

Default cookie lifetime in seconds.

net.inet.sctp.init_rtx_max

Initial retransmission timeout in milliseconds.

net.inet.sctp.assoc_rtx_max

Maximum number of retransmissions per association.

net.inet.sctp.path_rtx_max

Maximum number of retransmissions per association.

net.inet.sctp.nr_outgoing_streams

Default number of outgoing streams.

57
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

4.8 net.inet.tcp Variables


net.inet.tcp.always_keepalive

If TRUE, assume SO_KEEPALIVE on all TCP connections. Use this variable to reset
the current value of the TCP_ALWAYS_KEEPALIVE_CFG configuration parameter.

net.inet.tcp.blackhole

If TRUE, tells the stack not to send RST when dropping refused connections. Use
this variable to reset the current value of the TCP_BLACKHOLE_CFG configuration
parameter.

net.inet.tcp.delacktime

Sets the time before a delayed ACK is sent. Use this variable to reset the current
value of the TCP_DELACKTIME_CFG configuration parameter.

net.inet.tcp.delayed_ack

Enable delayed ACK feature. ACK is delayed until it can be piggybacked on to a


data packet. Use this variable to reset the current value of the
TCP_DELACK_ENABLED_CFG configuration parameter.

net.inet.tcp.do_tcpdrain

Enable tcp_drain routine for extra help when low on mbufs. Use this variable to
reset the current value of the DO_TCPDRAIN_CFG configuration parameter.

net.inet.tcp.drop_synfin

If TRUE, drop TCP packets with SYN+FIN set. Use this variable to reset the current
value of the TCP_DROP_SYNFIN configuration parameter.

net.inet.tcp.icmp_may_rst

If TRUE, ICMP unreachable messages can abort SYN_SENT connections. Use this
variable to reset the current value of the ICMP_MAY_RST_CFG configuration
parameter.

net.inet.tcp.inflight_debug

If TRUE, display the results of TCP inflight calculations. Use this variable to reset
the current value of the TCP_INFLIGHT_DEBUG configuration parameter.

58
4 Modifying Parameters at Run-time
4.8 net.inet.tcp Variables

net.inet.tcp.inflight_enable

If TRUE, enable automatic TCP inflight data limiting. Use this variable to reset the
current value of the TCP_INFLIGHT_ENABLE configuration parameter.

net.inet.tcp.inflight_max
4
Sets the upper bound for the TCP inflight window. Use this variable to reset the
current value of the TCP_INFLIGHT_MAX configuration parameter.

net.inet.tcp.inflight_min

Sets the lower bound for the TCP inflight window. Use this variable to reset the
current value of the TCP_INFLIGHT_MIN configuration parameter.

net.inet.tcp.isn_reseed_interval

Sets the number of seconds between the reseeding of a random ISN secret. This is
normally set to zero because reseeding should not be necessary. Use this variable
to reset the current value of the TCP_SEQ_ISNSEED_INTERVAL configuration
parameter.

net.inet.tcp.keepidle

Sets the TCP keepalive: idle time before first probe. Use this variable to override
the TCP_KEEPIDLE_CFG configuration parameter.

net.inet.tcp.keepinit

Sets the TCP keepinit. Use this variable to reset the current value of the
TCP_KEEPINIT_CFG configuration parameter.

net.inet.tcp.keepintvl

Sets the TCP keepalive: interval between probes when no response is received.
Use this variable to reset the current value of the TCP_KEEPINTVL_CFG
configuration parameter.

net.inet.tcp.local_slowstart_flightsize

Slow start flight size for local networks. Use this variable to reset the current value
of the TCP_LOCAL_SLOWSTART_FLIGHTSIZE_CFG configuration parameter.

59
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet.tcp.log_in_vain

If TRUE, the stack logs all incoming TCP connections. Use this variable to reset the
current value of the TCP_LOG_IN_VAIN_CFG configuration parameter.

net.inet.tcp.msl

Sets the TCP maximum segment lifetime. Use this variable to reset the current
value of the TCP_MSL_CFG configuration parameter.

net.inet.tcp.mssdflt

Set the default TCP maximum segment size. Use this variable to reset the current
value of the TCP_MSSDFLT_CFG configuration parameter.

net.inet.tcp.newreno

If TRUE, enables NewReno Algorithms. Use this variable to reset the current value
of the TCP_DO_NEWRENO_CFG configuration parameter.

net.inet.tcp.path_mtu_discovery

If TRUE, enable Path MTU discovery. Use this variable to reset the current value of
the TCP_PATH_MTU_DISCOVERY_CFG configuration parameter.

net.inet.tcp.pcbcount

Reports the number of active PCBs (protocol control blocks).

net.inet.tcp.pcblist

Reports a list of active TCP connections.

net.inet.tcp.recvspace

Sets the maximum incoming TCP datagram size. Use this variable to reset the
current value of the TCP_RECVSPACE_CFG configuration parameter.

net.inet.tcp.rexmit_min

Sets the minimum retransmission timeout.

net.inet.tcp.rexmit_slop

Sets the retransmission timer slop value.

60
4 Modifying Parameters at Run-time
4.8 net.inet.tcp Variables

net.inet.tcp.rfc1323

If TRUE, enable RFC 1323 (high performance TCP) extensions. Use this variable to
reset the current value of the TCP_DO_RFC1323_CFG configuration parameter.

net.inet.tcp.rfc1644
4
If TRUE, enable RFC 1644 (TTCP) extensions. Use this variable to reset the current
value of the TCP_DO_RFC1644_CFG configuration parameter.

net.inet.tcp.rttdflt

Sets the default maximum TCP round trip time.

net.inet.tcp.sendspace

Sets the maximum outgoing TCP datagram size. Use this variable to reset the
current value of the TCP_SENDSPACE_CFG configuration parameter.

net.inet.tcp.slowstart_flightsize

Slow start flight size. Use this variable to reset the current value of the
TCP_SLOWSTART_FLIGHTSIZE_CFG configuration parameter.

net.inet.tcp.syncookies

If TRUE, use TCP SYN cookies if the syncache overflows.

net.inet.tcp.tcbhashsize

Target size of TCP PCB hash tables. Must be a power of two. The default is 512.

net.inet.tcp.stats

Lists TCP statistics.

net.inet.tcp.v6mssdflt

Sets the default TCP maximum segment size for IPv6. Use this variable to reset the
current value of the TCP_V6MSSDFLT_CFG configuration parameter.

61
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

4.9 net.inet.tcp.syncache Variables


net.inet.tcp.syncache.bucketlimit

Sets the per-bucket limit for syncache.

net.inet.tcp.syncache.cachelimit

Sets the entry limit for syncache.

net.inet.tcp.syncache.count

Reports the current number of entries in syncache.

net.inet.tcp.syncache.hashsize

Sets the size of the TCP syncache hash table.

net.inet.tcp.syncache.rexmtlimit

Sets a limit on SYN/ACK retransmissions.

4.10 net.inet.udp Variables


net.inet.udp.blackhole

If TRUE, tells the stack not to send port unreachable messages for refused
connections. Use this variable to reset the current value of the
UDP_BLACKHOLE_CFG configuration parameter.

net.inet.udp.checksum

If TRUE, enables UDP checksum. Use this variable to reset the current value of the
UDPCKSUM_CFG configuration parameter.

net.inet.udp.log_in_vain

If TRUE, turns on logging of all incoming UDP packets. Use this variable to reset
the current value of the UDP_LOG_IN_VAIN_CFG configuration parameter.

62
4 Modifying Parameters at Run-time
4.11 net.inet6.icmp6 Variables

net.inet.udp.maxdgram

Sets the maximum outgoing UDP datagram size. Use this variable to reset the
current value of the UDP_MAXDGRAM_CFG configuration parameter.

net.inet.udp.pcblist
4
Reports the list of active UDP sockets.

net.inet.udp.recvspace

Sets the maximum incoming UDP datagram size. The default is


UDP_RECVSPACE_CFG, which is set in INCLUDE_UDPV4.

net.inet.udp.stats

Reports UDP statistics.

4.11 net.inet6.icmp6 Variables


net.inet6.icmp6.errppslimit

Specifies the per-second limit on ICMPv6 error packets. Use this variable to reset
the current value of the ICMPV6CTL_ERRPPSLIMIT_CFG configuration parameter.

net.inet6.icmp6.nd6_debug

Enables the ND6 debug option. Use this variable to reset the current value of the
ND6_DEBUG_CFG configuration parameter.

net.inet6.icmp6.nd6_delay

Specifies the ND6 delay first probe time (seconds). Use this variable to reset the
current value of the ND6_DELAY_CFG configuration parameter.

net.inet6.icmp6.nd6_drlist

Use this parameter to print the ND6 default router list.

63
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet6.icmp6.nd6_maxnudhint

Specifies the ND6 maximum number of subsequent upper layer hints. Use this
variable to reset the current value of the ND6_MAXNUDHINT_CFG configuration
parameter.

net.inet6.icmp6.nd6_mmaxtries

Specifies the ND6 maximum multicast query tries. Use this variable to reset the
current value of the ND6_MMAXTRIES_CFG configuration parameter.

net.inet6.icmp6.nd6_prlist

Use this parameter to print the ND6 prefix list.

net.inet6.icmp6.nd6_prune

Specifies the interval (in seconds) between walks of the ND6 list. Use this variable
to reset the current value of the ND6_PRUNE_CFG configuration parameter.

net.inet6.icmp6.nd6_maxqueuelen

Specifies the maximum number of packets cached in unresolved neighbor


discovery entries.

net.inet6.icmp6.nd6_umaxtries

Specifies the maximum unicast query tries for ND6. Use this variable to reset the
current value of the ND6_UMAXTRIES_CFG configuration parameter.

net.inet6.icmp6.nd6_useloopback

Specifies that ND6 use the loopback interface for local traffic. Use this variable to
reset the current value of the ND6_USELOOPBACK_CFG configuration parameter.

net.inet6.icmp6.nodeinfo

Specifies the response to the ICMPv6 NI enable/disable. The default is the


ICMPV6CTL_NODEINFO_CFG configuration parameter.

net.inet6.icmp6.rediraccept

Specifies that the stack accept and process ICMPv6 redirects. Use this variable to
reset the current value of the ICMPV6CTL_REDIRACCEPT_CFG configuration
parameter.

64
4 Modifying Parameters at Run-time
4.12 net.inet6.ip6 Variables

net.inet6.icmp6.redirtimeout

Specifies the ICMPv6 redirect cache time out (in seconds). Use this variable to reset
the current value of the ICMPV6CTL_REDIRTIMEOUT_CFG configuration
parameter.
4
net.inet6.icmp6.stats

Reports ICMPv6 statistics.

4.12 net.inet6.ip6 Variables


net.inet6.ip6.accept_rtadv

Allows the acceptance of IPv6 routing advertisements. Use this variable to reset
the current value of the IPV6CTL_ACCEPT_RTADV_CFG configuration parameter.

net.inet6.ip6.auto_flowlabel

Enables IPv6 auto flow label. Use this variable to reset the current value of the
IPV6CTL_AUTO_FLOWLABEL_CFG configuration parameter.

net.inet6.ip6.auto_linklocal

Assigns the IPv6 automatic link-local address. Use this variable to reset the current
value of the IPV6CTL_AUTO_LINKLOCAL_CFG configuration parameter.

net.inet6.ip6.dad_count

Specifies the maximum number of DAD (duplicate address detection) packets


generated, without a response, before putting an IPv6 address into operational
mode. Use this variable to reset the current value of the
IPV6CTL_DAD_COUNT_CFG configuration parameter.

net.inet6.ip6.defmcasthlim

Specifies the default hop limit for IPv6 multicasting. Use this variable to reset the
current value of the IPV6CTL_DEFMCASTHLIM_CFG configuration parameter.

65
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet6.ip6.forwarding

Allow IPv6 forwarding (act as an IPv6 router). Use this variable to reset the current
value of the IPV6CTL_FORWARDING_CFG configuration parameter.

net.inet6.ip6.gifhlim

Specifies the default hop limit for the gif encapsulated packets. Use this variable to
reset the current value of the IPV6CTL_GIF_HLIM_CFG configuration parameter.

net.inet6.ip6.hdrnestlimit

Specifies the maximum number of extension headers allowed per packet. Use this
variable to reset the current value of the IPV6CTL_HDRNESTLIMIT_CFG
configuration parameter.

net.inet6.ip6.hlim

Specifies the IPv6 hop limit. Use this variable to reset the current value of the
IPV6CTL_DEFHLIM_CFG configuration parameter.

net.inet6.ip6.ip6_mcast_pmtu

Enables path MTU discovery for IPv6 multicast forwarding.

net.inet6.ip6.keepfaith

Enables IPv6 keepfaith. Use this variable to reset the current value of the
IPV6CTL_KEEPFAITH_CFG configuration parameter.

net.inet6.ip6.log_interval

Specifies the minimum amount of time elapsed, in seconds, before next IPv6 debug
log message generation is allowed. Use this variable to reset the current value of
the IPV6CTL_LOG_INTERVAL_CFG configuration parameter.

net.inet6.ip6.maxfragpackets

Specifies the maximum number of IPv6 packets in the reassembly queue. Use this
variable to reset the current value of the IPV6CTL_MAXFRAGPACKETS_CFG
configuration parameter.

66
4 Modifying Parameters at Run-time
4.12 net.inet6.ip6 Variables

net.inet6.ip6.redirect

Allow redirects when IPv6 forwarding. Use this variable to reset the current value
of the IPV6CTL_SENDREDIRECTS_CFG configuration parameter which is set in
INCLUDE_IPV6.
4
net.inet6.ip6.rip6stats

Reports statistics for IPv6 raw packets.

net.inet6.ip6.rr_prune

Specifies the IPv6 walk timer value (in seconds) for router renumbering. Use this
variable to reset the current value of the IPV6CTL_RR_PRUNE_CFG configuration
parameter.

net.inet6.ip6.rtexpire

Specifies the IPv6 cloned route expiration time (seconds). Use this variable to reset
the current value of the IPV6CTL_RTEXPIRE_CFG configuration parameter.

net.inet6.ip6.rtmaxcache

Specifies the maximum number of cached IPv6 routes. This values serves as the
trigger-level for dynamic expire. Use this variable to reset the current value of the
IPV6CTL_RTMAXCACHE_CFG configuration parameter.

net.inet6.ip6.rtminexpire

Specifies the IPv6 minimum expiration time value (seconds). Use this variable to
reset the current value of the IPV6CTL_RTMINEXPIRE_CFG configuration
parameter.

net.inet6.ip6.rttimeout

Specifies the timeout (seconds) for cached routes. Use this variable to reset the
current value of the IPV6CTL_RTTIMEOUT_CFG configuration parameter.

net.inet6.ip6.stats

Reports IPv6 statistics.

net.inet6.ip6.use_deprecated

Allows the deprecated IPv6 address (RFC 2462 5.5.4). Use this variable to reset the
current value of the IPV6CTL_USE_DEPRECATED_CFG configuration parameter.

67
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

net.inet6.ip6.use_tempaddr

Allows the use of IPv6 temporary addresses (RFC 3041). Use this variable to reset
the current value of the IPV6CTL_USETEMPADDR_CFG configuration parameter.

net.inet6.ip6.temppltime

Specifies the maximum duration, in seconds, for preferred addresses. This is how
long to use the address in preference to other addresses. For example, to choose
this address when starting a connection.

net.inet6.ip6.tempvltime

Specifies the maximum duration, in seconds, for valid addresses. For example, a
system could continue using a connection that has a valid address even after it
should stop using that address to create new connections. When the valid address
expires, it should no longer be used. Contrast this parameter with temppltime.

net.inet6.ip6.v6only

Configures the stack to restrict AF_INET6 sockets to IPv6 traffic (by default they
can exchange IPv4 traffic too). Use this variable to reset the current value of the
IPV6CTL_V6ONLY_CFG configuration parameter.

4.13 net.link.ether.inet Variables


The default values for these parameters are taken from the parameters associated
with the INCLUDE_IPV4 component.

net.link.ether.inet.gratuitous_arp

If TRUE, send gratuitous ARP when a link/inet is enabled.

net.link.ether.inet.host_down_time

The number of seconds between running the ARP flooding algorithm.

net.link.ether.inet.log_arp_wrong_iface

When TRUE, the stack logs the ARP packets that arrive on the wrong interface.

68
4 Modifying Parameters at Run-time
4.13 net.link.ether.inet Variables

net.link.ether.inet.max_age

The number of seconds for which an ARP entry remains valid after it is resolved.

net.link.ether.inet.maxtries

The maximum number of tries for an IP address before pausing. 4

net.link.ether.inet.proxyall

When TRUE, proxy ARP is enabled.

net.link.ether.inet.prune_intvl

The number of seconds between checking the ARP list.

net.link.ether.inet.useloopback

Use this variable to configure the stack to use the loopback interface.

69
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

70
5
Configuring Transport and
Network Protocols
TCP, UDP, IP, ICMP

5.1 Introduction 71
5.2 Configuring IPv4 Components 73
5.3 Configuring IPv6 Components 85
5.4 Configuring VxWorks for Network Show Routines 91

5.1 Introduction
This chapter covers the transport and network layer protocols implemented for the
Wind River Network Stack. It describes the components and configuration
parameters that provides support for these protocols.

TCP, UDP, SCTP, and IPv6 “Jumbograms”

To provide transport layer functionality, the network stack includes


implementations of the TCP (RFC 793), the UDP (RFC 768), and the SCTP
(RFC 2960) protocols.
UDP provides a simple datagram-based end-to-end communication mechanism
without features such as flow control, guaranteed delivery, or the idea of two-way
communication. Those features are provided by TCP, a connection-oriented
transport-layer protocol. Both TCP and UDP rely on a port address to define
communication endpoints.

71
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This port address is an extension to the Internet address (whether IPv4 or IPv6) of
the host that contains the communication endpoint. Thus, changes to the
underlying IP protocol have not necessitated any great changes to either UDP or
TCP. The ability of IPv6 to carry a jumbogram, a packet containing a payload
longer than 65,535 octets, has provided a new opportunity that has required some
changes to UDP and TCP. These changes, described in RFC 2675, have been
included in this stack’s implementations of TCP, UDP, and supporting software.
Although SCTP was originally developed to transport PSTN signaling messages
over IP networks, it is capable of broader applications. Like TCP, SCTP is a reliable
transport layer protocol. However, SCTP also provides services not available from
TCP. For more information on these additional services, see 6. Using SCTP.

IPv6 Addressing Architecture

The core RFC for IPv6 is RFC 2460. This RFC describes the new packet header
format for IPv6. The RFC also mentions support for flow labeling, improved
authentication/privacy capabilities, improved support for future options, and
expanded addressing capabilities. If you access IPv6 from a high level and do not
expect to construct an IPv6 packet directly, the expanded 128-bit address is the
most relevant of the new IPv6 features.
The details of the IPv6 addressing architecture are not included in RFC 2460. That
information is provided in RFC 3513, which defines the addressing conventions
that divide the IPv6 address space into special uses, such as multicast addresses,
as well as addresses reserved for future use.

ICMP

IP hosts use the Internet Control Message Protocol (ICMP) to note and report any
errors encountered when processing a packet. Hosts also use ICMP for
Internet-layer diagnostics (echo requests and echo replies associated with ping).
The IPv4 side of the Wind River Network Stack implements ICMP as defined by
RFC 792. The IPv6 side of the stack implements ICMP as defined by RFC 2463. In
addition, the IPv6 side of the Wind River Network Stack implements RFC 2461,
the RFC for the Neighbor Discovery Protocol (NDP), which defines five new ICMP
packet types.
For information on ICMPv4 routing, see 16.7 Using the ICMPv4 Router Discovery
Server, p.347.

72
5 Configuring Transport and Network Protocols
5.2 Configuring IPv4 Components

5.2 Configuring IPv4 Components


The Wind River Network Stack supports network IPv4 protocol components for
the transport and network OSI layers:

TCP v4

TCP Debugging

UDP v4 5

IP v4

RAW v4

ICMP v4

Attach END to IPv4
These components are listed under the
Network Components > Network Protocol Components >
Network IPv4 Components and under the
Network Components > Network Private Components folders in Workbench.

TCP v4

The INCLUDE_TCPV4 component pulls in tcpLib and the other modules that
provide IPv4 support for TCP. This component requires the INCLUDE_IPV4
component.
This component supports the following configuration parameters:

DO_TCPDRAIN_CFG

Synopsis: Allow tcp_drain( ) to empty TCP reassembly queues.


Default: TRUE

TCP_MSSDFLT_CFG

Synopsis: Default TCP Maximum segment size.


Default: 512

TCP_DO_RFC1323_CFG

Synopsis: Enable RFC 1323 (high performance TCP) extensions.


Default: TRUE

73
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

TCP_DO_RFC1644_CFG

Synopsis: Enable RFC 1644 (TTCP) extensions.


Default: FALSE

TCP_SEQ_ISNSEED_INTERVAL

Synopsis: Number of seconds between the reseeding of a random ISN secret.


Default: 0

This is normally set to zero because reseeding should not be necessary.

TCP_INFLIGHT_ENABLE

Synopsis: Restrict TCP transmit window to maximize bandwidth?


Default: FALSE

TCP_INFLIGHT_DEBUG

Synopsis: Display the results of the TCP inflight calculations?


Default: FALSE

TCP_INFLIGHT_MIN

Synopsis: Lower bound for TCP inflight bandwidth delay product.


Default: 6144

TCP_INFLIGHT_MAX

Synopsis: Upper bound for TCP inflight bandwidth delay product.


Default: (65535 << 14)

TCP_KEEPINIT_CFG

Synopsis: The connection establishment timeout in milliseconds


Default: 75000

TCP_KEEPIDLE_CFG

Synopsis: Milliseconds before the first probe. (keepalive: idle)


Default: 7200000

74
5 Configuring Transport and Network Protocols
5.2 Configuring IPv4 Components

TCP_KEEPINTVL_CFG

Synopsis: Milliseconds between probes if no response. (keepalive: interval)


Default: 75000

TCP_KEEPCNT_CFG

Synopsis: Maximum failed keepalive probes before dropping connection 5


Default: 8

TCP_DELACKTIME_CFG

Synopsis: Timeout in milliseconds for sending a delayed ACK.


Default: 100

TCP_MSL_CFG

Synopsis: TCP Maximum Segment Lifetime (in milliseconds).


Default: 30000

TCP_ALWAYS_KEEPALIVE_CFG

Synopsis: Assume SO_KEEPALIVE on all TCP connections.


Default: FALSE

TCP_SENDSPACE_CFG

Synopsis: Default send socket buffer size for TCP endpoints.


Default: (1024*16)

TCP_RECVSPACE_CFG

Synopsis: Default receive socket buffer size for TCP endpoints.


Default: (1024*16)

TCP_LOG_IN_VAIN_CFG

Synopsis: Log all incoming TCP connections.


Default: FALSE

The value you specify here is effective only if you have recompiled the stack
with the preprocessor macro TCP_LOG_IN_VAIN defined as a non-zero
numeric value.

75
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

TCP_BLACKHOLE_CFG

Synopsis: Do not send an RST when dropping refused connections.


Default: FALSE

TCP_DELACK_ENABLED_CFG

Synopsis: Delay ACK. Try to piggyback it onto a data packet.


Default: TRUE

TCP_DROP_SYNFIN_CFG

Synopsis: Drop TCP packets with SYN+FIN set.


Default: FALSE

TCP_PATH_MTU_DISCOVERY_CFG

Synopsis: Enable Path MTU Discovery.


Default: TRUE

TCP_REASS_GLOBAL_MAX_CFG

Synopsis: Maximum total number of segments in reassembly queues.


Default: 512

TCP_REASS_ENDPT_MAX_CFG

Synopsis: Maximum TCP reassembly queue segments per endpoint.


Default: -1

Maximum number of segments in a reassembly queue. If negative, use


heuristic based on the MSS and the receive socket buffer size.

TCP_SLOWSTART_FLIGHTSIZE_CFG

Synopsis: Slow start flight size.


Default: 1

TCP_LOCAL_SLOWSTART_FLIGHTSIZE_CFG

Synopsis: Slow start flight size for local networks.


Default: 65535

76
5 Configuring Transport and Network Protocols
5.2 Configuring IPv4 Components

TCP_DO_NEWRENO_CFG

Synopsis: Enable NewReno Algorithms.


Default: TRUE

TCP Debugging
5
The INCLUDE_TCP_DEBUG component pulls in the tcp_debug library and other
modules that implement the TCP debugging functionality. This component
requires the INCLUDE_TCPV4 configuration component. There are no
user-callable functions or configuration parameters associated with these
modules.
To access the debug functionality pulled in by this component, set the SO_DEBUG
option on the socket endpoint you are debugging. If you set tcpDebugCons, a
global variable, to 1, then TCP debugging output is sent to standard output for the
running task. However, this can severely interfere with performance, and it might
lead to deadlock if writing to the standard output file descriptor requires another
task to enter network code (that is, to take the splnet( ) semaphore). As an
alternative, leave tcpDebugCons set to zero. Then, to output the buffered TCP
debug information after the fact, call tcpDebugShow( ), a routine provided by the
INCLUDE_TCP_SHOW component.

UDP v4

The INCLUDE_UDPV4 component pulls in udpLib and other modules that


implement UDP over IPv4. This component requires the INCLUDE_IPV4
component.
The INCLUDE_UDPV4 component supports the following configuration
parameters:

UDPCKSUM_CFG

Synopsis: Enable UDP checksum.


Default: TRUE

UDP_LOG_IN_VAIN_CFG

Synopsis: Log all incoming UDP packets.


Default: FALSE

77
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The value you assign to this parameter is ignored if you have not rebuilt the
stack with UDP_LOG_IN_VAIN defined as a preprocessor macro with a
nonzero numeric value.

UDP_BLACKHOLE_CFG

Synopsis: Do not send port unreachable for refused connections.


Default: FALSE

UDP_MAXDGRAM_CFG

Synopsis: Maximum outgoing UDP datagram size.


Default: 9216

For an individual socket connection, you can use the SO_SNDBUF socket
option to override the limit set here.

UDP_RECVSPACE_CFG

Synopsis: Maximum incoming UDP datagram size.


Default: 42080

Use this parameter to set the default maximum buffer usage per socket for
queuing received UDP datagrams. For an individual socket connection, you
can use the SO_RECVBUF socket option to override the limit set here.

IP v4

The INCLUDE_IPV4 component provides your network stack with the modules
that implement the data-plane functionality associated with IPv4. Almost none of
this functionality is directly accessible to user applications, although they can use
sysctl( ) to make run-time changes to the configuration values here.
This component requires the following components:

SELECT_NET_INIT
■ INCLUDE_NET_POOL

INCLUDE_ROUTE_STORAGE

INCLUDE_ROUTE
■ INCLUDE_DOMAIN_INIT
This component supports the following configuration parameters:

78
5 Configuring Transport and Network Protocols
5.2 Configuring IPv4 Components

IPPORT_RESERVED_CFG

Synopsis: Lowest non-privileged port number.


Default: 1024

IPPORT_RESERVEDSTART_CFG

Synopsis: Lowest dynamically assigned privileged port. 5


Default: 600

IPPORT_USERRESERVED_CFG

Synopsis: Highest dynamically assigned port number in normal range.


Default: 5000

IPPORT_HIFIRSTAUTO_CFG

Synopsis: First dynamically assigned port number in high range.


Default: 49152

IPPORT_HILASTAUTO_CFG

Synopsis: Last dynamically assigned port number in high range.


Default: 65535

IPFORWARDING_CFG

Synopsis: Enable IP forwarding between interfaces.


Default: ipForwardCfg
The value of ipForwardCfg depends on how the stack was compiled. For a
router stack, ipForwardCfg is TRUE, which means forwarding is enabled. For
a host stack, ipForwardCfg is FALSE. To set the value independently of how
the stack was built, replace the ipForwardCfg entry with TRUE or FALSE.

IPSENDREDIRECTS_CFG

Synopsis: Enable sending IP redirects.


Default: TRUE

IP_DEFTTL_CFG

Synopsis: Maximum TTL on IP packets.


Default: 64

79
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

IP_DOSOURCEROUTE_CFG

Synopsis: Enable forwarding of source-routed IP packets.


Default: FALSE

IP_ACCEPTSOURCEROUTE_CFG

Synopsis: Enable accepting source-routed IP packets.


Default: FALSE

IP_CHECKINTERFACE_CFG

Synopsis: Verify that the packet arrives on the correct interface.


Default: FALSE

IPSTEALTH_CFG

Synopsis: IP Stealth enabler.


Default: FALSE

Setting this parameter to TRUE has no effect in you have not recompiled the
stack with IPSTEALTH defined. In a default build, IPSTEALTH is undefined.

RTEXPIRE_CFG

Synopsis: Default expiration time on dynamically learned routes.


Default: (60*60)

RTMINEXPIRE_CFG

Synopsis: Minimum time to retain dynamically learned routes.


Default: 10

RTMAXCACHE_CFG

Synopsis: Upper limit on dynamically learned routes.


Default: 128

SUBNETS_ARE_LOCAL_CFG

Synopsis: in_localaddr includes subnets of the local net to test an address.


Default: FALSE

Use this parameter to set the flag that controls whether in_localaddr needs to
include other subnets of the local net when it tests an address.

80
5 Configuring Transport and Network Protocols
5.2 Configuring IPv4 Components

ARP_MAX_ENTRIES_CFG

Synopsis: Maximum number of ARP entries.


Default: 0

The default value of zero configures for an unlimited table. To reset this value
at run-time, call Sysctl( ) on arpMaxEntries.
5
ARP_PRUNE_INTVL_CFG

Synopsis: Number of seconds between checking ARP list.


Default: (5*60)

To reset this value at run-time, call Sysctl( ) on prune_intvl.

ARP_MAX_AGE_CFG

Synopsis: Number of seconds for which an ARP entry remains valid.


Default: (20*60)

To reset this value at run-time, call Sysctl( ) on max_age.

ARP_HOST_DOWN_TIME_CFG

Synopsis: ARP flooding algorithm pause value (in seconds).


Default: 20

Use this parameter to set the number of seconds to refrain from sending ARPs
after the destination host is considered to be down. To reset this value at
run-time, call Sysctl( ) on host_down_time.

ARP_MAXTRIES_CFG

Synopsis: Maximum number of tries for an IP address before pausing.


Default: 5

To reset this value at run-time, call Sysctl( ) on maxtries.

ARP_USELOOPBACK_CFG

Synopsis: Use loopback driver for local traffic?


Default: TRUE

To reset this value at run-time, call Sysctl( ) on useloopback.

ARP_PROXYALL_CFG

81
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Synopsis: Enable Proxy ARP?


Default: FALSE

To reset this value at run-time, call Sysctl( ) on proxyall.

ARP_GRATUITOUS_CFG

Synopsis: If TRUE, gratuitous ARP is sent when link/inet is enabled.


Default: FALSE

LOG_ARP_WRONG_IFACE_CFG

Synopsis: Log ARP packets arriving on the wrong interface?


Default: TRUE

To reset this value at run-time, call Sysctl( ) on log_arp_wrong_iface.

IPV4_RT_DISP_TBL

Synopsis: Assigns IPv4 route table storage method (default is Patricia tree).
Default: ptRibDispatchTable

The default, ptRibDispatchTable, references an ipRouteDispatchTable


structure populated with functions that implement a patricia tree for storing
routes. The ptRibDispatchTable structure is populated in ptRouteNodeLib.c,
which also defines the functions referenced in ptRibDispatchTable.
As an alternative, you could specify avlRibDispatchTable, which references
an ipRouteDispatchTable structure populated with functions that implement
an Adelson-Velskii and Landis balanced binary search tree (an AVL tree) to
store route entries. The avlRibDispatchTable structure is populated in
avlRouteNodeLib.c, which also defines the functions referenced in
avlRibDispatchTable. An AVL tree is preferred because it outperforms a
patricia tree if the route table is very large.
If you want to implement an alternative route storage method, your method
must support the entry points expected in an ipRouteDispatchTable
structure, and those entry points must conform to the APIs shown in
ptRouteNodeLib.c and avlRouteNodeLib.c.

FASTFORWARDING_CFG

Synopsis: Enable flow-based IP forwarding.


Default: FALSE

82
5 Configuring Transport and Network Protocols
5.2 Configuring IPv4 Components

RAW v4

The INCLUDE_RAWV4 component pulls in modules in support of raw IPv4


sockets. There are no user-callable functions associated with this component. This
component requires INCLUDE_IPV4.
This component supports the following configuration parameters:
5
RAW_MAXDGRAM_CFG

Synopsis: Maximum outgoing raw IP datagram size.


Default: 8192

For an individual socket connection, you can use the SO_SNDBUF socket
option to override the limit set here.

RAW_RECVSPACE_CFG

Synopsis: Maximum incoming raw IP datagram size.


Default: 8192

For an individual socket connection, you can use the SO_RECVBUF socket
option to override the limit set here.

ICMP v4

The INCLUDE_ICMPV4 component pulls in icmpLib and other modules that


implement ICMP for IPv4. This component requires INCLUDE_ICMPV4.
This component supports the following configuration parameters:

ICMPMASKREPL_CFG

Synopsis: Accept ICMP Mask Reply incoming packets.


Default: FALSE

ICMP_DROP_REDIRECT_CFG

Synopsis: Drop ICMP Redirect incoming packets.


Default: FALSE

83
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

ICMP_LOG_REDIRECT_CFG

Synopsis: Log ICMP Redirect incoming packets.


Default: FALSE

ICMPLIM_CFG

Synopsis: ICMP error-response bandwidth limit (-1 to disable).


Default: 200

ICMPBMCASTECHO_CFG

Synopsis: ICMP broadcast echo.


Default: TRUE

ICMP_MAY_RST_CFG

Synopsis: May ICMP unreachable abort TCP connections in SYN_SENT.


Default: TRUE

ICMPERRORLEN_CFG

Synopsis: The size, in bytes, of the ICMPv4 error message payload.


Default: 64

The ICMP error message payload consists of an ICMP message header


followed by a sample from the start of the bad packet that triggered the ICMP
error. The ICMP error message header requires eight bytes. At one time, a
sample of eight bytes from the bad packet was considered sufficient. However,
with the advent of IP tunneling and other technologies, this message sample
has been found to be insufficient.
A sample of 56 bytes has proven to be adequate for most tunneled messages.
Thus, the default is 64 bytes, which allows eight bytes for the ICMP header
plus 56 for the sample of the bad packet. If you find that you need a larger
sample of the bad packet, increase ICMPERRORLEN_CFG to any value not
greater than 488 bytes. This upper limit is imposed by the maximum size of an
ICMP datagram.

84
5 Configuring Transport and Network Protocols
5.3 Configuring IPv6 Components

NOTE: When working with the protocolcltinput( ) functions, such as pfctlinput( )


or the functions it calls, the sockaddr structure used to report the error message is
actually an icmp_info structure that has been cast as a sockaddr structure. The
icmp_info structure, defined in ip_icmp.h, is a sockaddr_in structure that has
been extended to include a new field, errorPktLen. This field reports the length of
the bad IP packet. For all non-ICMP error messages, the value of this field is zero.
5
If this extra information is not of interest to you, you can ignore it and continue
dealing with the ICMP error message as a sockaddr structure or sockaddr_in
structure. However, when working with ICMP error messages for tunnelled
packets, this length information can be convenient.

Attach END to IPv4

The INCLUDE_IPATTACH component configures the IPv4 stack to automatically


attach to the network interface specified in the boot line parameters. There are no
externally callable functions associated with this component. This component
requires the following components:
■ INCLUDE_NET_BOOT

INCLUDE_MUX

INCLUDE_IPV4

INCLUDE_NET_INIT
This component has no configuration parameters associated with it.

5.3 Configuring IPv6 Components


The Wind River Network Stack supports network IPv6 protocol components for
the transport and network OSI layers:

TCP v6

UDP v6

IP v6

RAW v6

ICMP v6

Attach END to IPv6

85
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

These components are listed under the


Network Components > Network Protocol Components >
Network IPv6 Components and under the
Network Components > Network Private Components folders in Workbench.

TCP v6

The INCLUDE_TCPV6 component provides IPv6 support for TCP. There are no
user-callable functions associated with this component.
The INCLUDE_TCPV6 component requires the INCLUDE_IPV6 component and
supports the following configuration parameters:
TCP_V6MSSDFLT_CFG
Synopsis: Default TCP Maximum Segment Size for IPv6.
Default: 1024

UDP v6

The INCLUDE_UDPV6 component pulls in the udp6 library and other modules that
implement IPv6 support for UDP. This component requires the INCLUDE_IPV6
component. There are no user-callable functions or configuration parameters
associated with this component.

IP v6

The INCLUDE_IPV6 component provides your network stack with the modules
that implement the data-plane functionality associated with IPv6. None of this
functionality is directly accessible to user applications. Thus, there are no library
reference entries directly associated with this configuration component.
This component requires the following components:

SELECT_NET_INIT

INCLUDE_NET_POOL
■ INCLUDE_LOOPBACK

INCLUDE_ROUTE_STORAGE

INCLUDE_ROUTE
■ INCLUDE_DOMAIN_INIT

86
5 Configuring Transport and Network Protocols
5.3 Configuring IPv6 Components


INCLUDE_ICMPV6

INCLUDE_ND

INCLUDE_TCPV6

INCLUDE_UDPV6
This component supplies the following configuration parameters:

IPV6CTL_FORWARDING_CFG 5
Synopsis: Allow IPv6 forwarding (act as an IPv6 router).
Default: FALSE, in a host stack. TRUE, in a router stack.

In some platforms, you can build the network stack code to support host stack
functionality or router stack functionality. The default value of this parameter
changes accordingly.

IPV6CTL_SENDREDIRECTS_CFG

Synopsis: Allow redirects when IPv6 forwarding.


Default: TRUE

IPV6CTL_DEFHLIM_CFG

Synopsis: IPv6 default hop limit


Default: 64

IPV6CTL_MAXFRAGPACKETS_CFG

Synopsis: Maximum number of IPv6 fragments in the reassembly queue.


Default: 16

IPV6CTL_ACCEPT_RTADV_CFG

Synopsis: Allows the acceptance of IPv6 routing advertisements.


Default: FALSE

IPV6CTL_KEEPFAITH_CFG

Synopsis: Enable IPv6 keepfaith.


Default: FALSE

IPV6CTL_LOG_INTERVAL_CFG

Synopsis: Time (seconds) until next IPv6 debug log message is allowed.
Default: 5

87
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

IPV6CTL_LOG_INTERVAL_CFG

Synopsis: Maximum number of extension headers allowed per packet.


Default: 50

IPV6CTL_DAD_COUNT_CFG

Synopsis: Maximum number of unresponded DAD packets generated.


Default: 1

At the end of this count, the stack transitions an IPv6 address into operational
mode.

IPV6CTL_AUTO_FLOWLABEL_CFG

Synopsis: Enable IPv6 auto flow label.


Default: TRUE

IPV6CTL_DEFMCASTHLIM_CFG

Synopsis: Default hop limit for IPv6 multicasting.


Default: 1

IPV6CTL_GIF_HLIM_CFG

Synopsis: Default hop limit for a gif-encapsulated packet.


Default: 30

IPV6CTL_USE_DEPRECATED_CFG

Synopsis: Allow the deprecated IPv6 address (RFC 2462, section 5.5.4).
Default: TRUE

IPV6CTL_RR_PRUNE_CFG

Synopsis: IPv6 walk timer value (seconds) for router renumbering.


Default: 5

IPV6CTL_V6ONLY_CFG

Synopsis: Configures the stack as an IPv6 only stack.


Default: FALSE

88
5 Configuring Transport and Network Protocols
5.3 Configuring IPv6 Components

IPV6CTL_AUTO_LINKLOCAL_CFG

Synopsis: Assign IPv6 automatic link-local address.


Default: TRUE

IPV6CTL_RTEXPIRE_CFG

Synopsis: IPv6 cloned route expiration time (seconds). 5


Default: 3600

IPV6CTL_RTMINEXPIRE_CFG

Synopsis: IPv6 minimum value for expiration time (seconds).


Default: 10

IPV6CTL_RTMAXCACHE_CFG

Synopsis: IPv6 maximum number of cached routes.


Default: 128

This value serves as the trigger-level for dynamic expire.

RAW v6

The INCLUDE_RAWV6 component pulls in modules in support of raw IPv6


sockets. There are no user-callable functions associated with this component. This
component requires the INCLUDE_IPV6 component.

ICMP v6

The INCLUDE_ICMPV6 component pulls in icmpv6Lib and other modules that


implement ICMPv6. There are no user-callable functions associated with this
component. This component requires the INCLUDE_IPV6 component.
This component supports the following configuration parameters:

ICMPV6CTL_REDIRACCEPT_CFG

Synopsis: Accept and process ICMPv6 redirects.


Default: FALSE

ICMPV6CTL_REDIRTIMEOUT_CFG

89
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Synopsis: ICMPv6 redirect cache time out (seconds).


Default: 600

ICMPV6CTL_NODEINFO_CFG

Synopsis: Response to the ICMPv6 NI enable/disable.


Default: 3

ICMPV6CTL_ERRPPSLIMIT_CFG

Synopsis: Per-second limit on error ICMPv6 packets.


Default: 100

Attach END to IPv6

The INCLUDE_IP6ATTACH component configures the IPv6 stack to automatically


attach to the network interface specified in the boot line parameters. There are no
externally callable functions associated with this component.
This component requires the following components:
■ INCLUDE_NET_BOOT

INCLUDE_MUX

INCLUDE_IPV6
■ INCLUDE_NET_INIT
This component supports the following configuration parameter:

IFF_INET6_UP_CFG

Synopsis: Enables RFC 2462 auto configuration for the boot interface.
Default: 1

RFC 2462 auto configuration lets a node create a link-local IPv6 address and verify
its uniqueness on a link using the Duplicate Address Detection procedure. If
necessary, the target can then use DHCP to negotiate for an assigned IPv6 address
of broader scope. This broader scope address is needed to make the node
addressable by IPv6 nodes outside the scope of its generated link-local address.

90
5 Configuring Transport and Network Protocols
5.4 Configuring VxWorks for Network Show Routines

5.4 Configuring VxWorks for Network Show Routines


The Wind River Network Stack supports the following network show routine
configuration components:

TCP Show Routines

UDP Show Routines

ICMP Show Routines 5

IGMP Show Routines

Network IP Show Routines

Network Interface Show Routines

Network Host Show Routines
These components are listed under the
Network Components > Network Utility Components >
Show Routine Components folder in Workbench.
For more information on the network show routines for routing, see Network Route
Show Routines, p.325.

TCP Show Routines

The INCLUDE_TCP_SHOW component pulls in the tcpShow library, which


provides tcpstatShow( ) for displaying TCP-related statistics. It also provides
tcpDebugShow( ). For more information on these routines, see the
tcpDebugShow( ) reference entry.
This component requires the INCLUDE_TCPV4 component and has no
configuration parameters.

UDP Show Routines

The INCLUDE_UDP_SHOW component pulls in the udpShow library, which


provides udpstatShow( ) for displaying UDP-related statistics. For more
information, see the udpstatShow( ) reference entry.
This component requires the INCLUDE_UDPV4 component and has no
configuration parameters.

91
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

ICMP Show Routines

The INCLUDE_ICMP_SHOW component pulls in the icmpShow library, which


provides the icmpstatShow( ) for displaying ICMP-related statistics. For more
information, see the icmpstatShow( ) reference entry. This component requires the
INCLUDE_ICMPV4 component.

IGMP Show Routines

The INCLUDE_IGMP_SHOW component pulls in the igmpShow library, which


provides igmpstatShow( ) for displaying IGMP-related statistics. For more
information, see the igmpstatShow( ) reference entries. This component requires
the INCLUDE_IGMP component.

Network IP Show Routines

The INCLUDE_NET_SHOW component pulls in the netShow library, which


provides functions such as inetstatShow( ) and inet6statShow( ). For more
information, see the netShow reference entries. This component requires the
INCLUDE_IPV4 component.

NOTE: If you want inetstatShow( ) to display TCP socket status, then you must
include INCLUDE_TCP_SHOW.

Network Interface Show Routines

The INCLUDE_NET_IF_SHOW component pulls in the ifShow library, which


supplies the ifShow( ) routine. You can use this routine to retrieve various
interface-related statistics. This component requires the INCLUDE_IPV4
component.

Network Host Show Routines

The INCLUDE_NET_HOST_SHOW component pulls in the hostShow library,


which supplies the hostShow( ) routine. This routine provides a list of remote
hosts, along with their Internet addresses and aliases. This component requires the
INCLUDE_HOST_TBL component.

92
6
Using SCTP

6.1 Introduction 93
6.2 Building and Configuring for SCTP 95
6.3 Understanding the SCTP Transport Layer 99
6.4 Working with SCTP 102

6.1 Introduction
This chapter describes how to use the Wind River implementation of SCTP, a
transport layer protocol that provides services not available from either TCP or
UDP. This chapter assumes that you are familiar with the SCTP protocol as
described in RFC 2960 and its companion documents.
The Wind River SCTP implementation is well contained. Thus, if you do not
require SCTP services, you can exclude it from your network stack.

NOTE: SCTP is available only in the Wind River Platforms builds of the network
stack. The Wind River General Purpose Platform, VxWorks Edition, does not
support SCTP.

93
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Supported Features

Although SCTP was originally developed to transport PSTN signaling messages


over IP networks, it is capable of broader applications. SCTP is a reliable transport
layer protocol. Like TCP, SCTP provides the following services to its users:

acknowledged error-free non-duplicated transfer of user data

data fragmentation to conform to discovered path MTU size
■ congestion avoidance behavior
However, SCTP also provides services not available from TCP. These additional
services are as follows:
■ sequenced delivery of user messages within multiple streams, with an option
for order-of-arrival delivery of individual user messages
■ optional bundling of multiple user messages into a single SCTP packet
■ network-level fault tolerance by supporting multi-home at either or both ends
of an association
■ resistance to flooding and masquerade attacks (included in the base protocol)
In addition to support for the generic SCTP services listed above, the Wind River
SCTP implementation specifically supports:
■ the basic features described in RFC 2960
■ the CRC-32 checksum algorithm described in RFC 3309
■ single instance sockets (one-to-one socket or TCP like sockets), described in
Sockets API Extensions for Stream Control Transmission Protocol1
■ a multi-home API, described in Sockets API Extensions for Stream Control Transmission
Protocol1

Unsupported Features

Not supported in the current Wind River SCTP implementation are:



IPv6 capability, described in RFC 2960

multi-instance sockets (one-to-many or UDP-like sockets), described in the
Internet draft, Sockets API Extensions for Stream Control Transmission Protocol

1. Sockets API Extensions for Stream Control Transmission Protocol, February 2005, R. Stewart, et
al., Internet Engineering Task Force - Transport Area Working Group. Work In Progress.
http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpsocket-10.txt

94
6 Using SCTP
6.2 Building and Configuring for SCTP


SCTP MIB from RFC 3873

multi-stack support (the SCTP module is not virtualized, thus, it cannot run on
a host running more than a single stack instance)

RTP support. Some support is inherent in using sockets, however this is not
tested and additional APIs have not been enhanced to work across the trap
boundary

Subjects Beyond the Scope of this Chapter 6

The SIGTRAN working group defined SCTP as the key transport mechanism to
transfer SS7 signaling messages over IP networks. Thus, there exist several user
adaptation layers that use SCTP services for transferring signaling information. It
is beyond the scope of this chapter to discuss the designs for user adaptation layers
(UAL) such as M3UA, M2UA, and M2PA.

Recommended Reading

The book listed below discusses sockets network programming in general, and it
has been updated for SCTP.
Unix Network Programming, Vol. 1: The Sockets Networking API, Third Edition, W.
Richard Stevens, Bill Fenner, and Andre M. Rudoff.

6.2 Building and Configuring for SCTP


This section explains how to build the network stack code to include SCTP and
how to configure VxWorks to include it.

6.2.1 Building the Network Stack to Support SCTP

SCTP is available only in the Wind River Platforms builds of the network stack. To
make the SCTP modules available for inclusion in a VxWorks image, you must
have previously built the network stack code with SCTP defined (-DSCTP). For
information on building the network stack, see Wind River Platforms Getting Started.

95
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

6.2.2 Configuring VxWorks for SCTP

The Wind River Network Stack supports the following NFS client configuration
components, which you can use to include the modules needed to create an NFS
client:

SCTP
This component is listed under the
Network Components > Network Protocol Components folder in Workbench.

SCTP

The INCLUDE_SCTP component pulls in modules that SCTP in a VxWorks image.


Including this component sets up a boot-time call to the sctpInstInit( ) routine,
which automatically initializes SCTP. This component requires the INCLUDE_IPV4
component and contains configuration parameters described in Setting
Configuration Parameters, p.96.

Setting Configuration Parameters

Associated with INCLUDE_SCTP component are configuration parameters that


you can use to manage the congestion control, slow start functionality, and more.

SCTP_SENDSPACE_CFG

Synopsis: Size of socket send buffer in bytes.


Default: 128 * 1024

SCTP_RECVSPACE_CFG

Synopsis: Size of socket receive buffer.


Default: 128 * (1024 + sizeof(struct sockaddr_in))

SCTP_AUTO_ASCONF_CFG

Synopsis: Determines whether to enable Auto-ASCONF.


Default: FALSE

96
6 Using SCTP
6.2 Building and Configuring for SCTP

SCTP_ECN_CFG

Synopsis: Determines whether to enable ECN.


Default: TRUE

SCTP_ECN_NONCE_CFG

Synopsis: Determines whether to enable ECN Nonce


Default: FALSE
6

SCTP_STRICT_SACKS_CFG

Synopsis: Determines whether to enable strict SACK checking.


Default: FALSE

SCTP_NO_CKSUM_ON_LOOPBACK_CFG

Synopsis: Determines whether to disable checksum on loopback. If set to


TRUE, do not compute or validate the checksum on packets that go
through loopback.
Default: TRUE

SCTP_STRICT_INIT_CFG

Synopsis: Determines whether to enable strict INIT/INIT-ACK singleton


enforcement.
Default: TRUE

SCTP_PEER_CHUNK_OH_CFG

Synopsis: Amount to debit receive window of peer per chunk sent.


Default: sizeof(struct mbuf)

SCTP_MAX_BURST_DEF_CFG

Synopsis: Default max burst for SCTP endpoints.


Default: 8

SCTP_MAX_CHUNKS_ON_QUEUE_CFG

Synopsis: Default max chunks on queue per association.


Default: 512

97
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

SCTP_DELAYED_SACK_TIME_DEF_CFG

Synopsis: Default delayed SACK timer.


Default: 200

SCTP_HEARTBEAT_INTERVAL_DEF_CFG

Synopsis: Default heartbeat interval (in ms).


Default: 30000

SCTP_DEF_PMTU_RAISE_SEC_CFG

Synopsis: Time (in seconds) to wait before trying to increase PMTU again.
Default: 600

SCTP_DEF_MAX_SHUTDOWN_SEC_CFG

Synopsis: Default shutdown guard timer in seconds.


Default: 180

SCTP_DEF_SECRET_LIFE_SEC_CFG

Synopsis: Default secret lifetime in seconds.


Default: 3600

SCTP_RTO_UPPER_BOUND_CFG

Synopsis: Maximum allowable value for retransmission timeout (in ms).


Default: 60000

SCTP_RTO_LOWER_BOUND_CFG

Synopsis: Minimum allowable value for retransmission timeout (in ms).


Default: 1000

SCTP_RTO_INITIAL_CFG

Synopsis: Initial retransmission timeout (in ms).


Default: 3000

98
6 Using SCTP
6.3 Understanding the SCTP Transport Layer

SCTP_DEFAULT_COOKIE_LIFE_CFG

Synopsis: Default cookie lifetime in seconds.


Default: 60

SCTP_DEF_MAX_INIT_CFG

Synopsis: Maximum number of retransmissions for INIT chunks.


Default: 8
6

SCTP_DEF_MAX_SEND_CFG

Synopsis: Maximum number of retransmissions per association.


Default: 10

SCTP_OSTREAM_INITIAL_CFG

Synopsis: Default number of outgoing streams.


Default: 10

SCTP_DEBUG_CFG

Synopsis: Turn on/off SCTP debugging.


Default: FALSE

NOTE: For each stream, SCTP uses a number of the smaller-sized buffers (such as
the 20-byte buffers) in the network stack system pool. If you expect to run a large
number of stream connections, you will need to adjust the number of smaller-sized
buffers. For information on adjusting the count of a particular buffer size in the
network stack system pool, see 3. Configuring and Managing Memory.

6.3 Understanding the SCTP Transport Layer


SCTP is a transport layer protocol that provides flexible data delivery and reliable
transfer over IP data networks. It is a reliable end-to-end protocol that delivers
data in independent streams in a multi-homed environment. It was originally
designed to address some shortcomings of TCP when transporting PSTN signaling
information over IP networks.

99
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

RFC Information

RFC 2960 describes the protocol for SCTP and a checksum algorithm. After
RFC 2960 was first published, weaknesses were discovered in the original
Adler-32 checksum algorithm. These weaknesses have been addressed in the
CRC-32 checksum algorithm, as described in RFC 3309.

TCP Shortcomings

As mentioned above, SCTP was originally designed to address some shortcomings


of TCP when transporting PSTN signaling information over IP networks.
RFC 2960 lists these shortcomings as follows:
■ TCP provides both reliable data transfer and strict order-of-transmission
delivery of data. Some applications need reliable transfer without sequence
maintenance, while others would be satisfied with partial ordering of the data.
In both cases, the head-of-line blocking offered by TCP causes unnecessary
delay.
■ The stream-oriented nature of TCP is often an inconvenience for
message-oriented applications. Such applications must add their own record
marking to delineate their messages, and they must make explicit use of the
push facility to ensure that a complete message is transferred in a reasonable
time.
■ The limited scope of TCP sockets complicates the task of providing highly
available data transfer capability using multi-homed hosts.
■ TCP is relatively vulnerable to denial of service (DoS) attacks, such as SYN
attacks.

SCTP Advantages

The following is a listing of advantages of SCTP. Currently, one standard


advantage, one-to-many (multi-instance) sockets, is not supported by the Wind
River SCTP implementation. For this reason, it is not listed below.

Message Boundaries

As mentioned above, TCP is a stream-oriented protocol. SCTP is a


message-oriented protocol, with the framing used by the sender maintained when
passing the message to the receiver. Messages that do not require fragmentation

100
6 Using SCTP
6.3 Understanding the SCTP Transport Layer

are carried in a single SCTP chunk. Larger messages are carried in a series of
associated chunks that allow the receiving SCTP engine to recreate the proper
message boundaries.

Reliable Data Transfer and Congestion Control

SCTP provides a reliable data transport service. It uses several mechanisms to


accomplish this. Each message includes a checksum to help ensure the integrity of
the message. The original specification used the Adler-32 checksum algorithm.
6
This has been replaced by the CRC-32 checksum algorithm in RFC 3309.
Included in each data chunk is a transmission sequence number or TSN. These tags
allow a receiving SCTP engine to acknowledge the receipt of a given chunk and to
detect the delivery of duplicate chunks. The receiving engine uses a selective
acknowledgment mechanism to indicate to the sender which chunks it has
received. Upon receiving this acknowledgment the sender can free resources
associated with the specified chunks, otherwise the receiver will re-transmit the
chunks after an appropriate time-out. The time-out period is adjusted over time to
account for potential congestion in the network.

Multiple Streams

TCP provides a single stream that can be blocked by a single delayed packet. SCTP
provides for multiple partially independent streams. The streams all share a
common congestion mechanism but are independent from a sequencing point of
view. A delayed data chunk affects only a single stream. Applications using other
streams will not see a disruption in their data.
In order to use multiple streams, an application needs to use the sendmsg( ) and
recvmsg( ) routines or some of the routines from the extended sctp_name( ) API.
The send( ), recv( ), sendto( ) and recvfrom( ) routines do not provide a
mechanism for passing the stream identifier between the application and the SCTP
engine.

Multi-Home

TCP is limited to a single address for each of its endpoints. SCTP allows each
endpoint to include multiple addresses and the SCTP engine will attempt to use a
different pair of addresses if traffic isn't flowing on the current pair.
In order to use the multi-home capabilities an application needs to use one of the
new APIs associated with SCTP, such as sctp_bindx( ) or sctp_connectx( ). These
allow an application to pass or retrieve a list of addresses from the SCTP engine.

101
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Protection Against DoS Attacks

TCP is not well protected against DoS attacks. During the initialization of an
association, SCTP uses a four-message handshake. This lets a server avoid saving
state for a requested association until after it has received a reply from the client.

6.4 Working with SCTP


This section covers the following topics for using SCTP:
■ 6.4.1 Using the Extended Socket API for SCTP, p.102
■ 6.4.2 Monitoring and Controlling SCTP, p.106
■ 6.4.3 Getting SCTP Status Information, p.107

6.4.1 Using the Extended Socket API for SCTP

Although the standard socket API is sufficient to access some SCTP functionality,
it does not support a parameter set that can encompass all of the functionality
provided by SCTP, in particular, the multi-home ability. To access this additional
SCTP functionality, you need to use a socket API that has been extended for SCTP.
Currently, the Wind River SCTP implementation supports the one-to-one interface
style but not the one-to-many style. A one-to-one style SCTP socket can control
only one SCTP association, and it is semantically similar to the standard socket
interface for connection-oriented protocols, such as TCP.

Creating an SCTP Socket

To access the extended socket API for SCTP, you must create a socket with a
protocol type of IPPROTO_SCTP. For example:
mySCTPsd = socket ( AF_INET, SOCK_STREAM, IPPROTO_SCTP );

Using the socket descriptor from such a socket( ) call, you can make either
standard socket calls or socket calls from the extended API. This extended API
includes support for SCTP’s multi-home functionality, which allows one to
associate multiple addresses with a socket endpoint.

102
6 Using SCTP
6.4 Working with SCTP

Standard and SCTP Sockets Compared

Table 6-1 provides a side-by-side listing of the standard socket interface and the
socket interface extended for use with SCTP. Keep in mind that, for SCTP sockets,
both the standard and the extended interface are supported.

Table 6-1 Standard versus the Extended (Multi-Home) Socket API for SCTP

Standard API Multi-Home API


6
STATUS bind int sctp_bindx
( (
int sd, int sd,
struct sockaddr *name, struct sockaddr *name,
int addrlen int addrcnt,
) int flags
)

STATUS listen
(
int sd,
int backlog
)

int accept
(
int sd,
struct sockaddr *addr,
int addrlen
)

STATUS connect int sctp_connectx


( (
int sd, int sd,
struct sockaddr *name, struct sockaddr *names,
int namelen int namescnt
) )

STATUS shutdown
(
int sd,
int how
)

103
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 6-1 Standard versus the Extended (Multi-Home) Socket API for SCTP (cont’d)

Standard API Multi-Home API

int sendmsg ssize_t sctp_sendmsg


( (
int sd, int sd,
struct msghdr *message, void *msg,
int flags size_t len,
) struct sockaddr *to,
socklen_t tolen,
uint32_t ppid,
uint32_t flags,
uint32_t stream_no,
uint32_t timetolive,
uint32_t context
)
ssize_t sctp_sendmsgx
(
int sd,
const void * msg,
size_t len,
struct sockaddr * addrs,
int addrcnt,
u_int32_t ppid,
u_int32_t flags,
u_int16_t stream_no,
u_int32_t timetolive,
u_int32_t context
)

int recvmsg ssize_t sctp_recvmsg


( (
int sd, int sd,
struct msghdr *message, void *msg,
int flags size_t len,
) struct sockaddr *from,
socklen_t *fromlen,
struct sctp_sndrcvinfo *sinfo,
int msg_flags
)

STATUS getpeername int sctp_getpaddrs


( (
int sd, int sd,
struct sockaddr *name, sctp_assoc_t id,
int *namelen struct sockaddr **addrs
) )

void sctp_freepaddrs
(
struct sockaddr *addrs
)

104
6 Using SCTP
6.4 Working with SCTP

Table 6-1 Standard versus the Extended (Multi-Home) Socket API for SCTP (cont’d)

Standard API Multi-Home API

ssize_t send int sctp_send


( (
FAST sd, int sd,
FAST const char * buf, void *msg,
FAST int bufLen, size_t len,
FAST int flags struct sctp_sndrcvinfo *sinfo,
) int flags 6
)

ssize_t sendto int sctp_sendx


( (
FAST int s, int sd,
FAST caddr_t *buf, void *msg,
FAST int bufLen, size_t len,
FAST int flags, sockaddr *addrs,
FAST struct sockaddr *to, int addrcnt,
FAST int tolen struct sctp_sndrcvinfo *sinfo,
) int flags
)

int recv
(
FAST int sd,
FAST char *buf,
FAST int bufLen,
FAST int flags
)

ssize_t recvfrom
(
FAST int sd,
FAST char *buf,
FAST int bufLen,
FAST int flags,
FAST struct sockaddr *pFrom,
FAST int *pFromlen
)

STATUS getsockopt int sctp_opt_info


( (
int sd, int sd,
int level, sctp_assoc_t id,
int optname, int opt,
char *optval, void *arg,
int *optlen socklen_t size
) )

105
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 6-1 Standard versus the Extended (Multi-Home) Socket API for SCTP (cont’d)

Standard API Multi-Home API

STATUS setsockopt
(
int sd,
int level,
int optname,
char *optval,
int optlen
)

STATUS getsockname int sctp_getladdrs


( (
int sd, int sd,
struct sockaddr *address, sctp_assoc_t id,
int *len struct sockaddr **addrs
) )
void sctp_freeladdrs
(
struct sockaddr *addrs
)

Because the SCTP socket calls are designed to fit into the standard socket system,
they use the same APIs whenever possible. In some cases, an argument is defined
as a void* to allow greater flexibility.

6.4.2 Monitoring and Controlling SCTP

Applications interested in monitoring their communications over SCTP first need


to use setsockopt( ) to register their interest in SCTP events and notifications. After
the setsockopt( ) call completes, these applications can use recvmsg( ) to receive
the SCTP events and notifications. To send control message to SCTP, applications
can make sendmsg( ) calls. Consider the following setsockopt( ) call:
/*
* We are interested in association change events and we want
* to get sctp_sndrcvinfo on each receive.
*/
memset( &events, 0, sizeof( struct sctp_event_subscribe ) );
events.sctp_association_event = 1;
events.sctp_data_io_event = 1;
ret = setsockopt( fd, IPPROTO_SCTP, SCTP_EVENTS, (char *) &events,
sizeof (events));

106
6 Using SCTP
6.4 Working with SCTP

For information on interpreting SCTP formats, see the following reference:


Unix Network Programming, Vol. 1: The Sockets Networking API, Third Edition,
W. Richard Stevens, Bill Fenner, Andre M. Rudoff.
This book discusses sockets network programming in general, and has been
updated for SCTP.

6.4.3 Getting SCTP Status Information 6

When running protocols such as TCP or UDP over SCTP, you can use the -a
netstat( ) option to retrieve socket/association information and statistics. For
example:
-> netstat "-a"
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 pcPentium.12865 pcPentium.1027 ESTABLISHED
tcp4 0 0 pcPentium.1027 pcPentium.12865 ESTABLISHED
tcp4 0 0 *.12865 *.* LISTEN
tcp4 0 0 *.ftp *.* LISTEN
tcp4 0 0 *.telnet *.* LISTEN
Active Stream Control Transmission Protocol associations (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
sctp 20000 0 localhost.58279 localhost.30464 ESTABLISHED
pcPentium.58279 pcPentium.30464
sctp 0 0 localhost.58279 *.* LISTEN
pcPentium.58279 *.*
sctp 0 0 localhost.30464 pcPentium.58279 ESTABLISHED
pcPentium.30464 localhost.58279
value = 0 = 0x0

To retrieve SCTP information alone, you can use the -a -p sctp netstat( ) options.
The listing above shows an SCTP server listening on a socket and another client
connected to it over loopback. For the statistics, you can use netstat( ) as follows:
-> netstat "-s -p sctp"
sctp:
1142209 :PEG_SACKS_SEEN
1142209 :PEG_SACKS_SENT
3582594 :PEG_TSNS_SENT
3582594 :PEG_TSNS_RCVD
3426892 :DATAGRAMS_SENT
3426892 :DATAGRAMS_RCVD
0 :RETRANTSN_SENT
0 :DUPTSN_RECVD
156 :HB_RECV
156 :HB_ACK_RECV
156 :HB_SENT
0 :WINDOW_PROBES

107
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

2284343 :DATA_DG_RECV
0 :TMIT_TIMER
5 :RECV_TIMER
0 :HB_TIMER
0 :FAST_RETRAN
165 :TIMERS_EXP
0 :FR_INAWINDOW
0 :RWND_BLOCKED
13 :CWND_BLOCKED
0 :RWND_DROPS
0 :BAD_STRMNO
0 :BAD_SSN_WRAP
0 :DROP_NOMEMORY
0 :DROP_FRAG
0 :BAD_VTAGS
0 :BAD_CSUM
3426892 :INPKTS
0 :IN_MCAST
0 :HDR_DROPS
0 :NOPORTS
13 :CWND_NOFILL
3973248 :CALLS_TO_CO
2230213 :CO_NODATASNT
1142159 :CWND_NOUSE_SS
171497 :MAX_BURST_APL
2101884 :EXPRESS_ROUTE
0 :NO_COPY_IN
4725131 :CACHED_SRC
0 :CWND_NOCUM
17 :CWND_SS
0 :CWND_CA
0 :CWND_SKIP
0 :CWND_NOUSE_CA
29152 :MAX_CWND
0 :CWND_DIFF_CA
26560 :CWND_DIFF_SA
0 :OQS_AT_SS
0 :SQQ_AT_SS
0 :OQS_AT_CA
0 :SQQ_AT_CA
29152 :MOVED_MTU
13 :MOVED_QMAX
0 :SQC_AT_SS
0 :SQC_AT_CA
546199 :MOVED_MAX
27163 :MOVED_NLEF
2024480 :NAGLE_NOQ
546173 :NAGLE_OFF
546173 :OUTPUT_FRM_SND
0 :SOS_NOSNT
2230213 :NOS_NOSNT
0 :SOSE_NOSNT
2230213 :NOSE_NOSNT
0 :DATA_OUT_ERR
0 :DUP_SSN_RCVD
0 :DUP_FR

108
6 Using SCTP
6.4 Working with SCTP

3426880 :VTAG_EXPR
4 :VTAG_BOGUS
0 :T3_SAFEGRD
0 :PDRP_FMBOX
0 :PDRP_FEHOS
0 :PDRP_MB_DA
0 :PDRP_MB_CT
0 :PDRP_BWRPT
0 :PDRP_CRUPT
0 :PDRP_NEDAT
0 :PDRP_PDBRK
value = 0 = 0x0 6

109
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

110
7
Enabling Virtual TCP/IP Stacks

7.1 Introduction 111


7.2 Configuring VxWorks for Virtual Stacks 112
7.3 Understanding Dual-Instance Network Stacks 115
7.4 Starting a Secondary Stack Instance 120
7.5 Using SNMP with Virtual TCP/IP Stack Instances 122
7.6 Using sysctl with Virtual Stacks 125

7.1 Introduction
If compiled with virtual stack support enabled, the Wind River Network Stack
IPv6 lets you run two TCP/IP stack instances on a single VxWorks target. Each
stack instance is data-independent of the other. This means that each stack has its
own routing table, network buffer memory pools, localized global variables, and
so on. In addition, each stack instance is designed to guarantee privacy at the
network layer.

NOTE: The TCP/IP virtual stacks feature is available only in Wind River Platforms
builds of the network stack. The Wind River General Purpose Platform, VxWorks
Edition, does not support virtual TCP/IP virtual stacks.

111
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Because each stack instance can guarantee network layer privacy, ISPs can use a
secondary stack instance within a single router in order to create virtual private
routed networks (VPRNs). These VPRNs let an ISP give each of its customers a
functionally private IP address space even though the same IP addresses might be
reused in the different stack instances.

NOTE: Virtual stacks are not supported in user space. In addition, if the stack has
been built with the VIRTUAL_STACK option, no networking feature can be used
from an RTP.

rlogin in Virtual Stacks Limitation

Using the rlogin application in the secondary virtual stack is possible only if you
have not already started the INCLUDE_NET_REM_IO utility in the first stack.
Among other scenarios, this requirement prevents the use of rlogin in the
secondary virtual stack when the VxWorks image downloads the symbol table. A
standalone image or an image that does not include symbols will allow rlogin to
run in either the primary or the secondary virtual stack instance.

NOTE: Virtual stack support is limited to two stack instances per target.

7.2 Configuring VxWorks for Virtual Stacks


The Wind River Network Stack supports the following virtual stack configuration
components:

Virtual Stack Library

Virtual Stack Core Initialization

Virtual Stack Application Initialization

Old Virtual Stack Library Wrapper Routines

Virtual Stack Show Routines

Virtual Stack Debug Support

Virtual Stack Example Code

Applications in Virtual Stack 0 Library
These components are all listed under the
Network Components > Virtual Stack Support folder in Workbench.

112
7 Enabling Virtual TCP/IP Stacks
7.2 Configuring VxWorks for Virtual Stacks

NOTE: These components are available to you only if the stack code was built
using -DROUTER_STACK and -DVIRTUAL_STACK. For information on building
the network stack, see your Wind River Platforms Getting Started.

Virtual Stack Library

The INCLUDE_VIRTUAL_STACK component pulls in vsLib and lets you specify


some fundamental virtual stack configuration values for shutting down a stack
7
instance. The initialization routine for this component calls vsLibInit( ) to initialize
the library, and vsCreate( ) to create virtual stack zero (VS0, also known as the
management stack). The INCLUDE_VIRTUAL_STACK component requires the
following configuration components:

INCLUDE_VIRTUAL_STACK_CORE_INIT

INCLUDE_VIRTUAL_STACK_APP_INIT

INCLUDE_APPL_IN_VIRTUAL_STACK
This component supports the following configuration parameters:

VIRTUAL_STACK

Synopsis: Turns on virtual stack support.


Default: NULL

Virtual stack support flag. This flag affects the compilation of numerous
modules throughout the network stack. After changing the value of this
parameter, you must rebuild all of the network stack code.

VS_DELTIMEO_CFG

Synopsis: Sets timeout value for stack deletion in system ticks.


Default: 7000

VS_SOCKTIMEO_CFG

Synopsis: Sets timeout value for closing sockets in system ticks.


Default: 1000

VS_APPLTIMEO_CFG

Synopsis: Sets additional timeout value for applications in system ticks.


Default: 0

113
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Virtual Stack Core Initialization

The INCLUDE_VIRTUAL_STACK_CORE_INIT component triggers the


initialization of core stack components. The initialization routine for the
component sets up an automatic call to vsStart( 0, VS_COMP), which handles
core component initialization for VS0. This initialization routine also calls
vsStatusSet( ) to set VS 0 into a running state, VS_RUNNING.
This component requires the INCLUDE_VIRTUAL_STACK component and has no
configuration parameters.

Virtual Stack Application Initialization

The component INCLUDE_VIRTUAL_STACK_APP_INIT triggers initialization of


application components. The initialization routine for this component calls
vsStart( 0, VS_APPS), which handles network application initialization for VS0.
This component requires the INCLUDE_VIRTUAL_STACK component and has no
configuration parameters.

Old Virtual Stack Library Wrapper Routines

The INCLUDE_VIRTUAL_STACK_OLD_INTERFACE component provides


backward compatibility with the 1.0 virtual stack API. If none of your code uses
this deprecated API, you can exclude this component.
This component requires the INCLUDE_VIRTUAL_STACK component and has no
configuration parameters.

Virtual Stack Show Routines

The INCLUDE_VIRTUAL_STACK_SHOW_FUNCTIONS component pulls in


vsShow, a library that provides virtual stack show routines.
This component requires the INCLUDE_VIRTUAL_STACK component and has no
configuration parameters.

114
7 Enabling Virtual TCP/IP Stacks
7.3 Understanding Dual-Instance Network Stacks

Virtual Stack Debug Support

The INCLUDE_VIRTUAL_STACK_DEBUG component pulls in vsDeb, a library


that provides debug routines for the virtual stack.
This component requires the INCLUDE_VIRTUAL_STACK component and has no
configuration parameters.

Virtual Stack Example Code


7
The INCLUDE_VIRTUAL_STACK_EXAMPLE component pulls in unsupported
example code for creating a virtual stack instance.
This component requires the INCLUDE_VIRTUAL_STACK component and has no
configuration parameters.

Applications in Virtual Stack 0 Library

The INCLUDE_APPL_IN_VIRTUAL_STACK component defines which applications


should be enabled for vs0. This component provides a configuration parameter for
each supported application. By default, these parameters are set to FALSE.

7.3 Understanding Dual-Instance Network Stacks


This section outlines the concepts and APIs that have been used to make the
VxWorks single-instance TCP/IP stack into a virtual-instance stack.

Localized Stack Global Variables

All global variables are collected into appropriate classes in order to assure that
virtualized instances of a particular component (for example, IP, TCP, and Routing
Tables) can coexist within the same flat memory space.
Consistent with the virtualization of global variables described above, the spl( )
routines for global blocking in a network stack have been modified to work with
stack-specific spl locks. Thus, when one stack instance takes its spl lock, it has no
impact on any other stack instance.

115
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Stack Instances Share a Common Task

From time to time, each network stack instance needs to run code within the
context of tNetTask. While a stack executes in tNetTask, that stack instance may
slightly delay all other stack instances. If a stack blocks in tNetTask, that stack will
eventually block all other stack instances.

7.3.1 Using Common Object Code

After booting successfully, a VxWorks target can automatically launch a network


stack instance known as the management stack or VS0. To launch an additional
stack instance, you must create a user project that contains startup code for the new
stack instance. For more information, see 7.4 Starting a Secondary Stack Instance,
p.120.
For a non-virtualized stack, the launch code for the stack automatically starts up
all network protocols and network applications included in the stack at build time.
For a virtualized stack, the startup code cannot assume that the inclusion of a
protocol or network application necessarily means that it should run in all stack
instances.

Configuring VS0

When the startup code initializes VS0, it initializes all core stack protocols and
applications included in the VxWorks image. Not all network stack components
included in a VxWorks image are necessarily core components. To determine
whether it should initialize a non-core component, the startup code relies on the
parameters to the INCLUDE_APPL_IN_VIRTUAL_STACK component. Each
parameter in INCLUDE_APPL_IN_VIRTUAL_STACK accepts a boolean value. If the
parameter value is TRUE, the associated application is initialized in VS0.
Otherwise, the application is not initialized for VS0.

Configuring the Secondary Stack

For a secondary stack, there is no automatic startup code. Instead, you need to
write your own code that calls the necessary stack configuration and startup
routines. By default, a secondary stack instance starts all the protocols and
applications enabled for VS0. You can use vsComponentStatusSet( ) to selectively
enable or disable the protocols and applications included in the stack. For more
information, see 7.4 Starting a Secondary Stack Instance, p.120.

116
7 Enabling Virtual TCP/IP Stacks
7.3 Understanding Dual-Instance Network Stacks

Overriding Build-Time Configuration Parameter Values

After using vsComponentStatusSet( ) to select the components you want enabled


for the secondary stack instance, you might want to use sysctl( ) to adjust the value
of selected network stack configuration parameters. You cannot use sysctl( ) to
reset all network stack configuration parameters. For example, you cannot
override the NUM_* values. These values control the network buffer pools and are
determined at build time for all stack instances. For a listing of network stack
parameters that sysctl( ) can reset at run-time, see 4. Modifying Parameters
at Run-time.
7

7.3.2 Stack Numbers versus VSIDs

In the preferred vsLib API for managing a virtual stack instance, you use a virtual
stack number to identify a stack instance. Internally, this number is interpreted as
an index into a table of pointers. Each pointer in this table references the head of a
system of structures that store the management data specific to a stack instance. In
the original vsLib API, some routines required you to supply not the index but the
pointer at that index location. That pointer is known as a Virtual Stack ID (VSID).

NOTE: Never directly access any data through its reference in a VSID. The internals
of the VSID are not part of the published API and could change in subsequent
releases. Your code should remain agnostic of the internals of the VSID.

7.3.3 Using Essential vsLib Routines

To manage two virtual stack instances on a single target device, use the interface
defined in vsLib.

Configuring and Creating a New Virtual Stack Instance

If you compile the network stack to include virtual stack support, you can initialize
virtual stack support by calling vsLibInit( ). If your image includes the
INCLUDE_VIRTUAL_STACK component, this call is made for you in the image
startup code.

117
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

At this point, you are ready to register the startup and shutdown routines for the
applications you want included in this network stack instance. For the Wind River
supplied network protocols and applications included in an image, registration is
handled for you automatically.
If you have written your own network stack protocol or application, you can call
vsComponentRegister( ) or vsApplicationRegister( ) to register your code’s
constructor and destructor routines. This is an optional step. It lets the stack
automatically start your application at initialization time.
When registering a protocol or application, you must specify whether it should be
enabled in the next stack instance to be created. If necessary, you can later use
vsComponentStatusSet( ) to reset this value. To check on the status of a registered
component or application, call vsComponentStatusGet( ).
All core network components supplied by Wind River are registered as enabled.
Non-core Wind River supplied applications register according to the parameters
supplied by the INCLUDE_APPL_IN_VIRTUAL_STACK configuration component.
These parameters report the values set at build time. It is possible that a run-time
call to vsComponentStatusSet( ) has since changed the registration to a different
state. This change would not be reflected in the values of the parameters to
INCLUDE_APPL_IN_VIRTUAL_STACK.
At this point, you are ready to call vsCreate( ), the routine that creates the virtual
stack instance. This routine does not initialize any network components or
applications for the stack it creates. To do that, you need to make at least two calls
to vsStart( ).
In the first vsStart( ) call, you should initialize the core components, those
registered by vsComponentRegister( ). After the first vsStart( ), use vsStatusSet( )
to set the stack’s state to VS_RUNNING. In the second vsStart( ) call, you should
initialize the code registered by vsApplicationRegister( ).
Finally, after you have a stack instance up and running, you must bind it to at least
one network interface. Call either ipAttach( ) or ip6Attach( ). In the case of VS0, the
stack binds automatically to the boot interface. For a secondary network stack, you
must explicitly bind the stack instance to an available interface. Keep in mind that
you may bind no more than one stack instance to a single network interface. Stack
instances cannot share a network interface. Thus, if VS0 is bound to the boot
interface, you cannot bind a secondary stack instance to the boot interface.

118
7 Enabling Virtual TCP/IP Stacks
7.3 Understanding Dual-Instance Network Stacks

Setting Stack Context prior to Requesting Network Services

To specify the virtual stack within which a task runs subsequent network service
requests, use vsIdContextSet( ).

! WARNING: If you use vsIdContextSet( ) to select the wrong stack instance, the next
network service call executes in an inappropriate context. The results are
unpredictable and almost certainly not what you intended.

By default, a newly initialized task assumes the management stack as its network
7
stack context. If you change the current stack context, the new stack context
remains until you explicitly change it. The only exception to this is when a shell
executes a routine that throws an exception. When the shell recovers from the
exception, it resets its stack context to the management stack.

Writing Task Routines for a Virtual Stack Environment

When writing a task routine, the routine specified in a taskSpawn( ) call, you
should include a parameter that lets the caller specify the stack number. Within
your task routine, your first act should be to call vsIdContextSet( ) to set the stack
context to whatever the caller passed in. Otherwise, your task routine runs in the
context of the management stack.

Executing a Wind Shell Command in a Specific Stack Context

When running a command from a Wind shell, the normal context-setting routines
mentioned above are ineffective. The assumed stack context is always stack 0, the
management stack. To run a command in a different stack context, you must call
vsexec( ). As input, this routine accepts a stack number, followed by the
command/routine name you want to run, followed by up to ten arguments to that
routine. For more information, see the vsexec( ) reference entry.

Showing Stack Information

Use vsShow( ) to show information for a TCP/IP stack instance that you specify
by stack number. If you do not specify a stack number, vsShow( ) prints a brief
description of each stack.

119
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

7.3.4 Using Sockets in Virtual Stacks

When you create a socket in a virtual stack, you are, by default, limited to using
that socket within that original stack context only. Attempting to use the socket in
any other stack context generates an error. This is the default behavior.
There are situations in which it can be convenient for a single socket to be
accessible from other virtual stack contexts. To allow this, set SO_VSLOCK, a
setsockopt( ) option, to zero. This socket option lets you configure individual
sockets so that they are accessible from any stack context. For the duration of the
call against the socket, the stack context switches to that of the socket’s origin. After
the operation completes, the stack context reverts to whatever it was before you
made the call against the socket.
If you are working with a socket and need to test whether it auto-switches, you can
use getsockopt( ) to discover the value of the socket’s SO_VSLOCK option.

7.4 Starting a Secondary Stack Instance


Use the vsLib API to start a secondary network stack instance in a deployed
system. The instructions in this section all use the vsLib API. However, if you
simply want to explore virtual stack functionality or to debug code that uses that
functionality, consider the convenience routines supplied by vsDeb.

NOTE: Do not use the vsDeb API in deployed applications. The functionality
supplied in vsDeb will be supported in the next release, but the details of the API
are almost certain to change. Thus, for deployed applications, applications for
which you want forward compatibility, use the vsLib API. Consider the vsDeb
API to be a deprecated API.

Using the vsLib API

Start a new stack instance as follows:


1. Build and then boot a VxWorks image that includes all network components
required by either VS0 or the secondary stack you intend to launch.

120
7 Enabling Virtual TCP/IP Stacks
7.4 Starting a Secondary Stack Instance

If this complete set of components includes more than you want to run in VS0,
you can use the INCLUDE_APPL_IN_VIRTUAL_STACK component parameters
to identify which non-core applications you want to exclude from VS0.
For the Wind River supplied network protocols and applications, including a
component automatically registers it with the virtual stack manager. If you
have written a network protocol or application, you can use either
vsComponentRegister( ) or vsApplicationRegister( ) to register your code’s
startup and shutdown routines with the virtual stack manager. This is not
required, but it is convenient when you must shutdown the stack and all its
applications in an orderly manner. 7

2. Use vsComponentStatusSet( ) to deactivate or activate components for the


secondary stack.
3. Call vsCreate( ) to create a stack instance.
4. Call vsStart( ) to initialize the network core components.
vsStart( 1, VS_COMP )

5. Activate the stack instance. Call vsStatusSet( ) and set the stack’s state to
VS_RUNNING.
6. Call vsStart( ) to initialize the network applications for the secondary stack.
vsStart( 1, VS_APPL )

7. Call ipAttach( ) or ip6Attach( ) to bind the stack to one or more network


interfaces.
Do not bind to any interface that is already bound to a stack. Although a single
stack can bind to many interfaces, that stack must have exclusive access to
those interfaces. Two stacks cannot share an interface.
8. Use ifconfig( ) to configure the interface and your routing table.
9. Start a loop-back instance for this stack instance.
This is handled for you automatically if INCLUDE_LOOPBACK is included in
the image, registered, and activated for the stack instance.

Debugging and Exploring Virtual Stacks

To display a listing of the vsDeb convenience routines, type vshelp on the


command line. If you have included vsDeb in the image, the command produces
a brief description of the available routines:

121
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


vshelp( ) - list available debugging commands

vscreate( ) - create a new (complete) virtual stack instance

vslist( ) - list status information for a virtual stack instance

vsset( ) - set virtual stack context of a running task/shell

vsscena( ) - enable a stack component for a specified virtual stack instance

vsscdis( ) - disable a stack component for a specified virtual stack instance

vsscshow( ) - show the status of virtual stack component(s)
■ vsscshowdis( ) - show disabled virtual stack component(s) per stack instance
■ vsscerr( ) - show the error status of virtual stack component(s)
■ vssta( ) - show the status of a virtual stack
■ vssglin( ) - call a single instance initialization routine
■ vssglde( ) - call a single destructor routine
■ vsstrt( ) - start an application in different stack contexts
In addition to those listed by vshelp, there are three additional routines:
■ vsdevl( ) - load and attach devices
■ vsdeva( ) - attach devices
■ vsdevrestart( ) - restart an interface on a new stack
These routines access functionality provided by the vsLib and vsShow libraries. In
a deployed application, access the vsLib and vsShow functionality directly.

7.5 Using SNMP with Virtual TCP/IP Stack Instances


When accessing information from a system, SNMP managers and agents use MIBs
to identify the specific piece of data that they seek. These MIBs require you to
specify the data down to a single object (such as a counter or a string) instead of an
aggregate (such as a C data structure). For the most part, these MIBs do not
provide methods that you can use to distinguish among copies of the same
information within a single target. This is a problem when managing two virtual
stack instances because there are several relevant MIBs (or parts of MIBs, such as
the system or IP groups) whose indexing does not allow for copies.
The Wind River solution is to use the SNMP feature known as contexts. A context
is a particular grouping of data. The current virtual stack code uses contexts to
represent the different virtual stacks.

122
7 Enabling Virtual TCP/IP Stacks
7.5 Using SNMP with Virtual TCP/IP Stack Instances

When working with SNMPv1 or SNMPv2c, use the community string to specify a
context. This is a standard overloading of this string. When working with
SNMPv3, use a context name to specify the proper context.
To access the different contexts, you need to program your SNMP manager to use
the proper community string or context name for the information you want to
examine. The default community string is comprised of a prefix of "VS" prepended
to the stack number as the string or name. Thus, you would use a community
string of "VS1" to access the information for virtual stack 1.
The community strings used as defaults in previous releases are unchanged and
7
will continue to access information relating to virtual stack 0, which is by default
the management stack.

Configuration

In support of virtual stacks, the configuration file (.cfg) for Wind River SNMP
supports two new options:
■ SNMP_VXWORKS_VIRTUAL_STACK

SNMP_VXWORKS_VS_ENTITY
The SNMP_VXWORKS_VIRTUAL_STACK option enables support for the new
handling of virtual stacks within Wind River SNMP. The
SNMP_VXWORKS_VS_ENTITY option adds information about the names used to
reach the virtual stacks into the logical entity table (entLogicalTable) from the
Entity MIB. For this option to be useful, you must also install the entity MIB. This
MIB is already a feature of Wind River SNMP and is installed under the option
ENVOY_ENTITY_MIB.
If you use the Makefile facility, configuration is largely automatic. If you include
VIRTUAL_STACK as an option on the command line, the facility turns on the
installation options that affect virtual stack support within Wind River SNMP and
support for two virtual stack instances (VS0 and VS1) is entered into the
appropriate tables.
In addition to options that enable virtual stack support in Wind River SNMP, there
are also several configuration options within the code. To access these options, edit
the standard Wind River SNMP porting file, envoy.h. These options and their
defaults are listed in Table 7-1.

123
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 7-1 Wind River SNMP Porting File Virtual Stack Options

Option Default

SNMP_VIRTUAL_STACK_NUM 2
SNMP_SET_VIRTUAL_STACK virtualStackNumTaskIdSet, which is now a
deprecated API. The default will change soon
to a supported routine.
NAMING_SCOPE_PREFIX "VS"
ENT_LOGICAL_DESCR "Virtual Stack #"
ENT_LOGICAL_TADDRESS "192.168.0.52"

Within envoy.h, there are additional options dealing with user exits for the virtual
stack functions. You should treat these as internal implementation artifacts and
leave their values unchanged.

Caveats

There are several items to keep in mind when using these SNMP features:
■ By default, the information for all virtual stacks is added to the tables at
initialization. This provides a simple mechanism for populating the tables. It
should be acceptable for most purposes if you plan to create all your virtual
stack instances at initialization. If you choose to create a virtual stack later, you
must consider the following:
– A manager querying the not yet created stack receives a timeout in
response to its request.
– A management request for a stack that has been created but not yet
initialized causes problems for the SNMP daemon.

By default, the VS_ENTITY option is installed. This causes the community
strings to be placed into the logical entity table (entLogicalTable) from which
they may be examined. You might want to keep this information more hidden.
The current version of the new solution does not interact well with deferred
processing routines (asynchronous method routines).

124
7 Enabling Virtual TCP/IP Stacks
7.6 Using sysctl with Virtual Stacks

7.6 Using sysctl with Virtual Stacks


Previously, all oids (nodes or variables), networking related or not were installed
into the sysctl tree using one of the many SYSCTL_* macros defined in:
installDir/vxworks-6.n/target/wrn/coreip/h/sys/sysctl.h
Example of those macros are:
■ SYSCTL_INT

SYSCTL_STRING

SYSCTL_NODE 7
To support a virtualized network stack and the resulting virtualized networking
sysctl sub-trees under a global kernel sysctl tree, the way the networking related
sysctl oids are installed was changed. The networking related sysctl oids are now
installed using SYSCTLN_* macros such as:

SYSCTLN_INT

SYSCTLN_STRING
■ SYSCTLN_NODE
Additionally, all top level nodes that go under the net node need to be installed
using the SYSCTLN_TOP_NODE macro. Any other networking node that is not a
top level networking node should be installed using the SYSCTLN_NODE macro
Previously, you used the macros as follows:
SYSCTL_NODE(net, PF_INET, inet, CTLFLAG_RW, 0, "Internet Family");
SYSCTL_NODE(inet, IPPROTO_IP, ip, CTLFLAG_RW, 0, "IP");
SYSCTL_NODE(inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP");

Now, you should use the macros as follows:


SYSCTLN_TOP_NODE(net, PF_INET, inet, CTLFLAG_RW, 0, "Internet Family");
/* This is a top level net node */
SYSCTLN_NODE(inet, IPPROTO_IP, ip, CTLFLAG_RW, 0, "IP");
SYSCTLN_NODE(inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP");

The non-networking related oids are still installed as previously, using the
SYSCTL_* macros.

125
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

126
8
Adding NFS Support

8.1 Introduction 127


8.2 Configuring VxWorks for an NFS Client 128
8.3 Creating an NFS Client 133
8.4 Configuring VxWorks for an NFS Server 139
8.5 Creating an NFS Server 143

8.1 Introduction
Wind River Network Stack implements the Network File System (NFS)
application protocol. The first part of this chapter describes how to configure and
use an NFS client, which enables a VxWorks target to mount remote file systems
and access the contents of those file systems as if they were local. The second part
of this chapter describes how to configure and use an NFS server, which enables a
VxWorks target to export local systems to remote network systems.

NOTE: VxWorks does not normally provide authentication services for NFS
requests, and the DOS file system does not provide file permissions. If you need
the NFS server to authenticate incoming requests, see the nfsdInit( ) and
mountdInit( ) reference entries for information on authorization hooks.

127
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

8.2 Configuring VxWorks for an NFS Client


The Wind River Network Stack supports the following NFS client configuration
components, which you can use to include the modules needed to create an NFS
client:

Core NFS Client

NFS Client All

NFS v2 Client

NFS v3 Client

NFS Mount All
These components are all listed under the
Network Components > Network Applications > NFS Components folder in
Workbench.

Core NFS Client

The INCLUDE_CORE_NFS_CLIENT component pulls in nfsCommon, a library that


provides core functionality for NFS clients. This library also provides parameters
that you can use to specify the NFS user ID, group identifier, and the maximum
length of the pathname for a file.
This component requires the INCLUDE_RPC and INCLUDE_BSD_SOCKET
components.
This component contains the following configuration parameters:

NFS_USER_ID

Synopsis: User identifier for NFS access.


Default: 2001

NFS_GROUP_ID

Synopsis: Group identifier for NFS access.


Default: 100

NFS_MAXPATH

Synopsis: Maximum file path length.


Default: 255

128
8 Adding NFS Support
8.2 Configuring VxWorks for an NFS Client

NFS Client All

Including the INCLUDE_NFS_CLIENT_ALL component is equivalent to selecting


both INCLUDE_NFS2_CLIENT and INCLUDE_NFS3_CLIENT, the components that
pull in client support for NFS version 2 and NFS version 3 respectively.
This component requires the INCLUDE_NFS2_CLIENT and
INCLUDE_NFS3_CLIENT components.

NFS v2 Client

8
The INCLUDE_NFS2_CLIENT component pulls in nfs2Lib and nfs2Drv, which
provide support of an NFS version two client. Using this client, you can mount
exported NFS (version two) directories to your VxWorks target.
This component requires the INCLUDE_CORE_NFS_CLIENT component.

Initialization

This component also configures the VxWorks image to initialize the NFS v2 client,
which includes a call to nfsAuthUnixSet( ):
nfsAuthUnixSet ( sysBootParams.hostName, NFS_USER_ID, NFS_GROUP_ID, 0,
(int *) 0);

Values for the NFS_USER_ID and NFS_GROUP_ID parameters are taken from the
required INCLUDE_CORE_NFS_CLIENT component.

Parameters

This component contains the following configuration parameters:

NFS2_CLIENT_CACHE_DEFAULT_NUM_LINES

Synopsis: Default number of cache lines.


Default: 16

The NFS client implementation uses a persistent cache, which is structured as


a multi-line buffer cache. This parameter configures the default number of
lines in the NFS v2 client cache. The value can be decreased to as low as 1, or
increased.
You can modify the number of cache lines, either at build time or at run-time.
To configure the cache at run time, call the routine usrNfs2CacheInit( ):
usrNfs2CacheInit (UINT32 numLines, UINT32 lineSize, UINT32 options);

129
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NFS2_CLIENT_CACHE_DEFAULT_LINE_SIZE

Synopsis: Default number of bytes in cache line.


Default: 16384

The NFS client implementation uses a persistent cache, which is structured as


a multi-line buffer cache. The cache line size must be a power of two.
This parameter configures the default size of the NFS v2 client cache line. The
default value for this is 16384 (16 kB). When combined with the default
number of cache lines, this yields a default cache size of 256 kB.
You can modify the number of cache line size, either at build time or at
run-time. To configure the cache at run time, call the routine
usrNfs2CacheInit( ):
usrNfs2CacheInit (UINT32 numLines, UINT32 lineSize, UINT32 options);

Changing the size of the cache will not affect any existing cache. It will only
impact future caches.

NFS2_CLIENT_CACHE_DEFAULT_OPTIONS

Synopsis: Default cache options.


Default: 0

This parameter configures the default options for the NFS v2 client cache. The
two valid settings for this parameter are:
0
The default value of zero (0) means that the cache will collect the written
data and only send it to the server when the cache line is full, or it needs
to be flushed (no options), which is the default value
1, NFS_CACHE_WRITE_THROUGH
A value of one means that the cache will be write-through.
You can modify the cache options, either at build time or at run-time. To
configure the cache at run time, call the routine usrNfs2CacheInit( ):
usrNfs2CacheInit (UINT32 numLines, UINT32 lineSize, UINT32 options);

NFS v3 Client

The INCLUDE_NFS3_CLIENT component pulls in the nfs3Lib and nfs3Drv


libraries, which provide support of an NFS version three client. Using this client,
you can mount exported NFS (version three) directories to your VxWorks target.

130
8 Adding NFS Support
8.2 Configuring VxWorks for an NFS Client

This component requires the INCLUDE_CORE_NFS_CLIENT component.

Initialization

This component also configures the VxWorks image to initialize the NFS v3 client,
which includes a call to nfsAuthUnixSet( ):
nfsAuthUnixSet ( sysBootParams.hostName, NFS_USER_ID, NFS_GROUP_ID, 0,
(int *) 0);

Values for the NFS_USER_ID and NFS_GROUP_ID parameters to this routine are
taken from the required INCLUDE_CORE_NFS_CLIENT component.

Parameters 8

This component contains the following configuration parameters:

NFS3_CLIENT_CACHE_DEFAULT_NUM_LINES

Synopsis: Default number of cache lines.


Default: 16

The NFS client implementation uses a persistent cache, which is structured as


a multi-line buffer cache. This parameter configures the default number of
lines in the NFS v3 client cache. The value can be decreased to as low as 1, or
increased.
You can modify the number of cache lines, either at build time or at run-time.
To configure the cache at run time, call the routine usrNfs3CacheInit( ):
usrNfs3CacheInit (UINT32 numLines, UINT32 lineSize, UINT32 options);

NFS3_CLIENT_CACHE_DEFAULT_LINE_SIZE

Synopsis: Default number of bytes in cache line.


Default: 16384

The NFS client implementation uses a persistent cache, which is structured as


a multi-line buffer cache. The cache line size must be a power of two.
This parameter configures the default size of the NFS v3 client cache line. The
default value for this is 16384 (16 kB). When combined with the default
number of cache lines, this yields a default cache size of 256 kB.
You can modify the number of cache line size, either at build time or at
run-time. To configure the cache at run time, call the routine
usrNfs3CacheInit( ):
usrNfs3CacheInit (UINT32 numLines, UINT32 lineSize, UINT32 options);

131
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Changing the size of the cache will not affect any existing cache. It will only
impact future caches.

NFS3_CLIENT_CACHE_DEFAULT_OPTIONS

Synopsis: Default cache options.


Default: 0

This parameter configures the default options for the NFS v3 client cache. The
two valid settings for this parameter are:
0
The default value of zero (0) means that the cache will collect the written
data and only send it to the server when the cache line is full, or it needs
to be flushed (no options), which is the default value
1, NFS_CACHE_WRITE_THROUGH
A value of one means that the cache will be write-through.
You can modify the cache options, either at build time or at run-time. To
configure the cache at run time, call the routine usrNfs3CacheInit( ):
usrNfs3CacheInit (UINT32 numLines, UINT32 lineSize, UINT32 options);

Configuring NFS3 Client Writes

The NFS v3 client has one additional configurable parameter that is not available
on NFS v2. According to the RFC, the NFS v3 client can dictate to an NFS v3 server
how it should perform the write operations. At runtime, the NFS v3 client can be
set to inform the server that it should perform writes one of the following styles:
■ UNSTABLE
■ FILE_SYNC
■ DATA_SYNC
The default setting is UNSTABLE.
You can use two routines to configure these options at run-time:

nfs3StableWriteSet(stable_how mode) lets you set the mode

nfs3StableWriteGet( ) routine gets the current mode

NOTE: This option does not exist in NFS v2.

132
8 Adding NFS Support
8.3 Creating an NFS Client

NFS Mount All

The INCLUDE_NFS_MOUNT_ALL component configures a VxWorks target to


make a boot-time call to nfsMountAll( ). This routine automatically mounts all file
systems exported by the boot host system.
This component requires the INCLUDE_NFS_CLIENT_ALL component.
This component contains the following configuration parameter:

GROUP_EXPORTS

Synopsis: Remove check for GroupName during MountAll. 8


Default: FALSE

An NFS server can specify that an exported file system is intended for particular
group of clients. Before mounting an exported file system, a client typically checks
that it is a group member. If the client is not a group member, it does not mount
the file system. To configure the client to skip this check, set this parameter to
TRUE. The default of FALSE ensures that the check occurs.

8.3 Creating an NFS Client


To create an NFS client and use it to access a remote networked file system:
1. Call nfs2Drv( ) or nfs3Drv( ) to initialize support for NFS v2 or v3 or both.
Normally, you should not need to call either of these routines explicitly.
VxWorks calls these routines automatically at boot time if the image includes
INCLUDE_NFS_CLIENT_ALL. For NFS v2 only, use INCLUDE_NFS2_CLIENT.
To initialize NFS v3 only, use INCLUDE_NFS3_CLIENT.
2. Call nfsAuthUnixSet( ) to configure the user name and user ID the device
should use when communicating with a particular host.
VxWorks calls nfsAuthUnixSet( ) automatically at boot time if the image
contains INCLUDE_NFS_CLIENT_ALL, INCLUDE_NFS2_CLIENT, or
INCLUDE_NFS3_CLIENT. The values for user name and user ID are supplied
by the parameters to INCLUDE_CORE_NFS_CLIENT.
3. Call hostAdd( ) to configure the host table to know of the host system from
which you want to mount an exported file system.

133
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

VxWorks calls hostAdd( ) for the host system automatically at boot time. If
you want to mount file systems from other remote systems, you need to make
and explicit hostAdd( ) call for those systems.
4. Call nfsMount( ) or nfsMountAll( ) to actually mount a remote file system.
The nfsMountAll( ) routine queries the specified remote system for a list of
exported file names and then creates NFS client device instances for each
exported file system. To unmount a file system, use nfsUnmount( ). Use
nfsDevShow( ) to display a list of the mounted NFS devices.
As a convenience, the INCLUDE_NFS_MOUNT_ALL component configures an
image to make a boot time call to nfsMountAll( ) to mount all file systems
exported by the boot host.
The following sections supplement and expand on the procedure outlined above.

Exporting File Systems from the Remote NFS Server

For a UNIX NFS server, the /etc/exports file specifies which of the server’s file
systems are exported for mounting by remote NFS clients. If a file system on a
UNIX NFS server is not listed in /etc/exports, the file system is not exported, which
means other machines cannot use NFS to mount it. For example, consider an
/etc/exports file that contains the line:
/usr

The server exports /usr without restriction. If you want to limit access to this
directory, you can include additional parameters on the line. For example:
1. On the UNIX box, login as root (super user).
2. Edit: /etc/exports
3. Specify the path and permission for the file system that you would export.
For example: /usr * (rw)
For more information on these parameters, consult your UNIX system
documentation.
4. Export the file system, run: exportfs -ra
5. On the UNIX target, run the NFS daemon: rpc.nfsd
6. Run: rpc.rquotad
7. To run mount the daemon, run: rpc.mountd
To check whether NFS is running, use: rpcinfo -p.

134
8 Adding NFS Support
8.3 Creating an NFS Client

Windows systems also support NFS. Thus, it is possible to configure a directory on


a Windows system so that it is exported over NFS. The exact procedures for doing
so depend upon the particular network package you purchased. For more
information, consult the documentation included with your Windows networking
package.

Setting Your NFS Client Name, User ID, and Group ID

Internally, NFS depends upon RPC to handle the remote execution of the
commands (open, read, write, and others) that access the data in the remote file
system. Associated with the RPC protocol is an authentication system known as 8
AUTH_UNIX. This authentication system requires RPC peers to provide a user
name, a user ID, and a group name. The recipient of an RPC message uses this
information to decide whether to honor or ignore the RPC request.
On a VxWorks host, you can set the NFS user name, user ID, and group name
using the NFS_GROUP_ID and NFS_USER_ID parameters included in the
INCLUDE_CORE_NFS_CLIENT component. You can also set these values by calling
nfsAuthUnixSet( ) or nfsAuthUnixPrompt( ). For example, to use
nfsAuthUnixSet( ) to set the NFS user ID to 1000 and the NFS group ID to 200 for
the machine mars, you would call nfsAuthUnixSet( ) as follows:
-> nfsAuthUnixSet "mars", 1000, 200, 0

The nfsAuthUnixPrompt( ) routine provides a more interactive way of setting the


NFS authentication parameters from the shell.
On UNIX systems, a user ID is specified in the file /etc/passwd. A list of groups that
a user belongs to is specified in the file /etc/group. To configure a default user ID
and group ID, set NFS_USER_ID and NFS_GROUP_ID. The NFS authentication
parameters will take on these values at system startup. If NFS file access is
unsuccessful, make sure that the configuration is correct.

Mounting a Remote File System

After setting your NFS client name, user ID, and group ID, you are ready to call
nfsMount( ) to mount any file system exported by a known host. To add a system
to the list of hosts known to a VxWorks system, call hostAdd( ):
hostAdd ("host", "IPaddress" )

This routine associates a host name with an IP address. Thus, if you wanted to
mount a file system exported by a system called "mars", you would need to have

135
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

already called hostAdd( ) for "mars". For example, if "mars" were at 192.168.10.1
you would need to call hostAdd( ) as follows:
hostAdd ("mars", "192.168.10.1" )

If "mars" exports a file system called /usr, you can now use a call to nfsMount( ) to
create a local mount of that remotely exported file system. The syntax of an
nfsMount( ) call is as follows:
nfsMount ("hostName", "hostFileSys", "localName")

hostName
The host name of the NFS server that exports the file system you want to
mount.
hostFileSys
The name of the host file system or subdirectory as it is known on the
exporting NFS server system.
localName
The local name to assign to the file system.
For example, if you wanted to mount a remote file system, /d0/, on your target,
wrs, as a device called /myDevice0/, you would make the following call to
nfsMount( ):
nfsMount ("wrs", "/d0/", "/myDevice0/");

The VxWorks target now has access to the contents of /d0/, although using the
device name, /myDevice0/. For example, if the remote device stores the file,
/d0/bigdog, you can access this file from the wrs target using the pathname,
/myDevice0/bigdog. If you want the local device to use the same device name
as is used on the exporting system, use a NULL as the third parameter of the
nfsMount( ) call. For example:
nfsMount ("wrs", "/d0/", NULL);

Or, from the kernel shell:


-> nfsMount "wrs", "/d0/"

On the VxWorks target, the nfsMount( ) call creates the local device, /d0/.
Thus, on the target, the pathname to bigdog is the same as on the exporting
system; that is: /d0/bigdog.
If you do not need to mount the remote file system under a new name, you should
consider using nfsMountAll( ) instead of nfsMount( ). A call to nfsMountAll( )
mounts all file systems that are exported from the remote system and that are
accessible to the specified client.

136
8 Adding NFS Support
8.3 Creating an NFS Client

The syntax of nfsMountAll( ) is as follows:


nfsMountAll( "hostName", "clientName", quietFlag )

hostName
The name of the host from which you want to mount all exported file
systems.
clientName
The name of a client specified in an access list, if any. A NULL clientName
mounts only those file systems that are accessible to any client.
quietFlag
A boolean value that tells nfsMountAll( ) whether to execute in verbose 8
or silent mode. FALSE indicates verbose mode, and TRUE indicates quiet
mode.

Using IOCTL Routines for Open Files from a Mounted Directory

After opening a file in a mounted directory, you can work with the file using the
IOCTL values listed in Table 8-1.

Table 8-1 Supported IOCTL Values for Files Accessed through NFS

IOCTL Description

FIOGETNAME Gets the file name of fd and copies it to the buffer referenced
by nameBuf:
status = ioctl (fd, FIOGETNAME, &nameBuf);

FIONREAD Copies to nBytesUnread the number of bytes remaining in


the file specified by fd:
status = ioctl (fd, FIONREAD, &nBytesUnread);

FIOSEEK Sets the current byte offset in the file to the position specified
by newOffset. If the seek goes beyond the end-of-file, the file
grows. The end-of-file pointer gets moved to the new
position, and the new space is filled with zeros:
status = ioctl (fd, FIOSEEK, newOffset);

FIOSYNC Flush data to the remote NFS file. It takes no additional


argument:
status = ioctl (fd, FIOSYNC, 0);

137
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 8-1 Supported IOCTL Values for Files Accessed through NFS (cont’d)

IOCTL Description

FIOWHERE Returns the current byte position in the file. This is the byte
offset of the next byte to be read or written. It takes no
additional argument:
position = ioctl (fd, FIOWHERE, 0);

FIOREADDIR Reads the next directory entry. Use the third argument in the
ioctl( ) call to supply a pointer to a directory descriptor of
type DIR.
DIR dirStruct;
fd = open ("directory", O_RDONLY);
status = ioctl (fd, FIOREADDIR, &dirStruct);

Normally, you do not use the FIOREADDIR functionality


directly. Instead, you would call readdir( ). See the reference
entry for dirLib.
FIOFSTATGET Gets file status information (directory entry data). Use the
third argument in the ioctl( ) call to supply a pointer to a stat
structure that is filled with data describing the specified file.
For example:
struct stat statStruct;
fd = open ("file", O_RDONLY);
status = ioctl (fd, FIOFSTATGET, &statStruct);

Normally, you do not use the FIOFSTATGET functionality


directly. Instead, you would stat( ) or fstat( ) routines get file
information. See the manual entry for dirLib.
FIOFSTATFSGET Gets the file system parameters for and open file descriptor.
Use the third argument in the ioctl( ) call to supply a pointer
to a statfs structure that is filled with data describing the
underlying file system.
statfs statfsStruct;
fd = open ("directory", O_RDONLY);
status = ioctl (fd, FIOFSTATFSGET, &statfsStruct);

Normally, you do not use the FIOFSTATFSGET functionality


directly. Instead, you would stat( ) or fstat( ) routines get file
information. See the manual entry for dirLib.

138
8 Adding NFS Support
8.4 Configuring VxWorks for an NFS Server

8.4 Configuring VxWorks for an NFS Server


The Wind River Network Stack supports the following NFS server configuration
components, which you can use to include the modules needed to create an NFS
server:

NFS Server

NFS server All

NFS server V2

NFS server V3
These components are all listed under the
Network Components > Network Applications > NFS Components folder in 8
Workbench.

NFS Server

The INCLUDE_CORE_NFS_SERVER component pulls in nfsd, the library that


supplies the NFS server daemon initialization routines.
For more information on these routines, see the nfsd reference entry. This
component also supplies configuration parameters that set basic configuration
values for the server.
The INCLUDE_CORE_NFS_SERVER component requires the INCLUDE_RPC and
INCLUDE_BSD_SOCKET components.

NOTE: The NFS server maintains a reply cache of up to 64 recently transmitted


reply messages. The purpose of this cache is to deal with RPC retransmissions. If
the XID of an incoming NFS request matches that of a previously replied message,
the cached reply is sent back instead of actually executing the NFS request.
Each entry in the server reply cache requires 8800 bytes for the entry itself and 48
bytes for each cache node. Thus, if there were three entries in the cache, the
memory usage would be 26,544 bytes, which is (3 * 8800) + (3 * 48) bytes. If there
were the full 64 entries in the cache, the memory usage would be 566,272 bytes.
If you think you have noticed a memory leak in NFS, please consider whether this
memory use accounts for the discrepancy.

139
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This component contains the following configuration parameters:

NFS_MAXPATH

Synopsis: Maximum length of a file path string (excludes file name).


Default: 255

NFS_USER_ID

Synopsis: User identifier for NFS access.


Default: 2001

NFS_MAXFILENAME

Synopsis: Maximum file name length. Valid values range from 1 to 99.
Default: 40

This parameter specifies the maximum length of a filename. If a filename is longer


than this value then it is truncated before returning it to the client. This parameter
should be set carefully since it affects the amount of memory allocated by the
server.
NFS_GROUP_ID

Synopsis: Group identifier for NFS access.


Default: 100

NFS server All

Including the INCLUDE_NFS_SERVER_ALL component is equivalent to selecting


both INCLUDE_NFS3_SERVER and INCLUDE_NFS2_SERVER.
This component requires the INCLUDE_NFS3_SERVER, INCLUDE_NFS2_SERVER,
and INCLUDE_NFS_SERVER_INSTALL components.

NFS server V2

The INCLUDE_NFS2_SERVER component pulls in nfs2dLib and mount1Lib. The


nfs2dLib library implements the NFS version 2 procedures as specified in the
Network File System Protocol Specification (RFC 1094).

140
8 Adding NFS Support
8.4 Configuring VxWorks for an NFS Server

The mount1Lib library implements a mount version one server to support


mounting VxWorks file systems remotely. The mount server is an implementation
of version 1 of the mount protocol as defined in RFC 1094.
The INCLUDE_NFS2_SERVER component requires the
INCLUDE_CORE_NFS_SERVER and INCLUDE_NFS_SERVER_INSTALL
components.

NOTE: VxWorks does not normally provide authentication services for NFS
requests, and the DOS file system does not provide file permissions. If you need to
authenticate incoming requests, see the documentation for nfsdInit( ) and
mountdInit( ) for information about authorization hooks.
8

To actually export a file system, you must call nfsExport( ).


Table 8-2 lists the requests that RFC 1813 accepted from clients. For details of their
use, see RFC 1094, NFS: Network File System Protocol Specification.

NFS server V3

The INCLUDE_NFS3_SERVER component pulls in nfs3dLib and mount3Lib. The


nfs3dLib library provides an implementation of the NFS version 3 procedures as
specified in the RFC 1813 (Network File System Protocol Specification). The
mount3Lib library implements a mount server. The mount server is an
implementation of version 3 mount protocol as defined in RFC 1813.
NFS version 3 requires mount versions 1 and 3. Also required are
INCLUDE_CORE_NFS_SERVER and INCLUDE_NFS_SERVER_INSTALL.
To actually export a file system, you must call nfsExport( ).
The INCLUDE_NFS3_SERVER component requires the
INCLUDE_CORE_NFS_SERVER and INCLUDE_NFS_SERVER_INSTALL
components.

NOTE: VxWorks does not normally provide authentication services for NFS
requests, and the DOS file system does not provide file permissions. If you need to
authenticate incoming requests, see the documentation for nfsdInit( ) and
mountdInit( ) for information about authorization hooks.

The following requests are accepted from clients. For details of their use, see RFC
1813: NFS: Network File System Protocol Specification.

141
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 8-2 RFC 1813 Supported Client Requests

Procedure Name Procedure Number

NFSPROC_NULL 0
NFSPROC_GETATTR 1
NFSPROC_SETATTR 2
NFSPROC_LOOKUP 3
NFSPROC_ACCESS 4
NFSPROC_READLINK 5 – not supported, limitation in DOSFS
NFSPROC_READ 6
NFSPROC_WRITE 7
NFSPROC_CREATE 8
NFSPROC_MKDIR 9
NFSPROC_SYMLINK 10 – not supported
NFSPROC_MKNOD 11 – not supported
NFSPROC_REMOVE 12
NFSPROC_RMDIR 13
NFSPROC_RENAME 14
NFSPROC_LINK 15 – not supported
NFSPROC_READDIR 16
NFSPROC_READDIRPLUS 17
NFSPROC_FSSTAT 18
NFSPROC_FSINFO 19
NFSPROC_PATHCONF 20
NFSPROC_COMMIT 21

142
8 Adding NFS Support
8.5 Creating an NFS Server

8.5 Creating an NFS Server


To set up an NFS file server on a VxWorks target, you need to configure the
VxWorks target to include the appropriate NFS server configuration components,
described in 8.4 Configuring VxWorks for an NFS Server, p.139. You also need a file
system for export, such as a DOS file system (dosFs). For more information on how
to do this on a VxWorks target, see the VxWorks Programmer’s Guide.
After you have a file system to export, call nfsExport( ) to export the specified file
system.

8
Initializing an NFS File System for Export

The following code fragment can create a RAM drive:


unsigned myBlockSize; /* block size in bytes */
unsigned myTotalSize; /* disk size in bytes */

myBlockSize = 512;
myTotalSize = 16777216; /* 16Mb */

xbdRamDiskDevCreate (myBlockSize, myTotalSize, FALSE, "/ramDrv");


dosFsVolFormat ("/ramDrv", 2, 0);
nfsExport ("/ramDrv", 0, FALSE, 0);

! CAUTION: For NFS-exportable file systems, the device name absolutely must not
end in a slash.

Exporting a File System through NFS

After you have an exportable file system, call nfsExport( ) to make it available to
NFS clients on your network. Then mount the file system from the remote NFS
client using the facilities of that system. The following example shows how to
export the new file system from a VxWorks target called vxTarget, and how to
mount it from a typical UNIX system.
1. After the file system (/export in this example) is initialized, the following
routine call specifies it as a file system to be exported with NFS:
nfsExport ("/export", 0, FALSE, 0);

The first three arguments specify the name of the file system to export; the
VxWorks NFS export ID (0 means to assign one automatically); and whether

143
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

to export the file system as read-only. The last argument is a placeholder for
future extensions.
2. To mount the file system from another machine, see the system documentation
for that machine. Specify the name of the VxWorks system that exports the file
system, and the name of the desired file system. You can also specify a
different name for the file system as seen on the NFS client.

! CAUTION: On UNIX systems, you normally need root access to mount file systems.

For example, on a typical UNIX system, the following command (executed


with root privilege) mounts the /export file system from the VxWorks system
vxTarget, using the name /mnt for it on UNIX:
-> /etc/mount vxTarget:/export /mnt

144
9
Adding Support for
Network Applications

9.1 Introduction 146


9.2 Ping 146
9.3 DNS 148
9.4 SNTP 152
9.5 FTP 155
9.6 TFTP 160
9.7 RSH 163
9.8 RPC 165
9.9 RLOGIN 167
9.10 Telnet 168
9.11 Changing the Default Login for FTP, FTPv6, and Telnet 173
9.12 Creating a netDrv Device for RSH or FTP 176

145
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

9.1 Introduction
This chapter describes the network application protocols implemented by the
Wind River Network Stack, and the configuration components and parameters
associated with each.
In support of remote login, the Wind River Network Stack includes the RSH
protocol as well as implementations of rlogin and telnet. Both rlogin and telnet
have been modified to support the identification of the remote site using either an
IPv4 or an IPv6 address.
The Wind River Network Stack implements the remote file access protocols RSH,
FTP, and TFTP for use with either IPv4 and IPv6 addresses. Using these protocols,
a VxWorks target can access the files on a remote networked machine as easily as
if the files were local to the VxWorks system. Going the other way, the Wind River
Network Stack implementations of these protocols (except RSH) let remote
networked machines access files on a VxWorks target just as transparently.
Programs running on the host need not know that the files they use are maintained
on the VxWorks system.
If your application requires direct access to the RSH, FTP, and TFTP protocol
implementations, it can do so. To simplify remote file access using the RSH or FTP
protocols, the Wind River Network Stack includes netDrv. Using this driver, you
can open, read, write, and close files located on remote systems without needing
to manage the details of the underlying protocol used to effect the transfer of
information. For more information on how to do this, see 9.12 Creating a netDrv
Device for RSH or FTP, p.176. For additional information, see the reference entries
for the following libraries: remLib, ftp6Lib, ftpd6Lib, tftpLib, and tftpdLib.

9.2 Ping
Packet InterNet Grouper (PING) is used to test of whether a particular host is
reachable and operating properly on the network. Ping works by sending ICMP
“echo request” packets to the target host and listening for replies (ICMP “echo
response” packets). The Wind River Network Stack implements the ping
application protocols for IPv4 and IPv6.

146
9 Adding Support for Network Applications
9.2 Ping

Configuring VxWorks for Ping

The Wind River Network Stack supports the following ping client configuration
components:

PING ICMP Client

PING6 ICMP Client
These components are all listed under the
Network Components > Network Applications folder in Workbench.

PING ICMP Client

9
The INCLUDE_PING component pulls in pingLib, the library that implements the
IPv4 ping( ) utility. By calling ping( ), you can check the network connection to a
remote host. The remote host must be running TCP/IP networking code that
responds to ICMP echo request packets. The ping( ) routine is re-entrant and thus
can be called concurrently from many tasks.

NOTE: When using ping( ) programmatically, you may want to use the
PING_OPT_SILENT option to suppress output. See the ping( ) reference entry for
more information on this and other ping( ) options.

PING6 ICMP Client

he INCLUDE_PING6 component pulls in ping6Lib, the library that implements the


IPv6 ping6( ) utility. Using ping6( ), you can check the network connection to a
remote host. The remote host must be running TCP/IP networking code that
responds to ICMP6 echo request packets.

WARNING: Unlike ping( ), the ping6( ) routine is not re-entrant.

147
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

9.3 DNS
Domain Name Server (DNS) is a distributed database that most TCP/IP
applications can use to translate host names to IP addresses and back. DNS uses a
client/server architecture. The client side is known as the resolver. The server side
is called the name server. For detailed information on DNS, see RFC 1034 and RFC
1035. For a description for IPv6 records, see RFC 3596. The Wind River
Network Stack includes both a resolver and a server.

Wind River Implementation

The Wind River Network Stack implementation of the resolver closely follows the
4.4 BSD resolver implementation, differing in the way it handles the hostent
structure.
The 4.4 BSD resolver is a library that links with each process and uses static
structures to exchange data with the process. This is not possible under VxWorks,
which uses a single copy of the library that it shares among all the tasks in the
system. All applications using the resolver library must provide their own buffers.
Thus, the routines resolvGetHostByName( ) and resolvGetHostByAnyAddr( )
require two extra parameters For more information, see the reference entries for
resolvGetHostByName( ) and resolvGetHostByAnyAddr( ).

NOTE: Neither resolvGetHostByName( ) nor resolvGetHostByAnyAddr( ) are


supported within an RTP.

The Wind River Network Stack resolver library uses UDP to send requests to the
configured name servers. The resolver also expects the server to handle any
recursion necessary to perform the name resolution. You can configure the
resolver at initialization or at run-time.1
In addition, you can configure how the resolver library responds to a failed name
server query. Either the resolver looks in the static host configuration table
immediately after the failed query, or the resolver ignores the static table.2 The
default behavior of the resolver is to query only the name server and ignore the
static table.

1. For initialization, call resolvParamsGet( ) and resolvParamsSet( ). See the reference


entries for these routines.
2. The static host name table is maintained by hostLib.

148
9 Adding Support for Network Applications
9.3 DNS

The resolver has been fully integrated into the Wind River Network Stack.
Existing applications can benefit from the resolver without needing to make any
code changes. This is because the code internal to hostGetByName( ) and
hostGetByAddr( ) has been updated to use the resolver.3
Thus, all you need do to take advantage of the resolver is to include it in your stack
and configure it (configuring the resolver involves specifying the server address
and domain).

NOTE: The current Wind River DNS resolver supports the feature set found in the
BIND 8.x DNS resolver only. Thus, it does not yet support features such as
DNAMEs and Bitstring.

9
Configuring VxWorks for DNS

The Wind River Network Stack supports the following DNS resolver
configuration component:

Domain Name Service Client

Domain Name Service Client Debug Output
This component is listed under the
Network Components > Network Applications folder in Workbench.

Domain Name Service Client

The INCLUDE_DNS_RESOLVER component pulls in resolvLib and other modules


that implement a DNS client known as the resolver. The services provided by this
resolver have been integrated with the services provided by hostLib.
Including INCLUDE_DNS_RESOLVER in a VxWorks image sets up a call to the
usrDnsInit( ) initialization routine, which is defined in the
net/coreip/apps/usrDnsCfg.c file.
The INCLUDE_DNS_RESOLVER component has no component dependencies.

NOTE: If you include the DNS resolver, INCLUDE_DNS_RESOLVER, you will need
to specify functioning values for its domain and domain server configuration
parameters.

3. Both hostGetByName( ) and hostGetByAddr( ) are hostLib routines.

149
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This component contains the following configuration parameters:

RESOLVER_DOMAIN

Synopsis: Specifies the domain in which this stack resides.


Default: "my.domain"

You must set RESOLVER_DOMAIN to a string containing the domain name to


which your organization belongs. The resolver uses this domain name when it
tries to query the domain server for the name of the host machine for its
organization.

RESOLVER_DOMAIN_SERVER

Synopsis: The IPv4 or IPv6 address of the DNS server to contact with queries.
Default: "192.168.0.6"

If you want to reach a server on an IPv4 network, enter a quoted string


containing the IPv4 address of the server (for example, "192.168.0.6"). To reach
a server on an IPv6 network, you can enter the global IPv6 address of the
server as a quoted string (for example: "2001:DB8::1"). If the IPv6 address is a
link-local only address, you must enter a quoted string of the format:
ipv6_address%interface
Where:
ipv6_address
is the IPv6 address of the server.
interface
is the name and number of the interface through which to reach the
server.
For example: "fe80::202:b3ff:fe9a:922e%fei0"
Before using the resolvLib functionality, the route table must contain a route
to the DNS server specified above. If you have included a routing protocol
such as RIP, the routing protocol might have added the route for you.
Otherwise, you will need to add the route manually using routec( ) or a
routing socket.

RES_TIMEOUT_CFG

Synopsis: Specifies the retransmission time interval.


Default: RES_TIMEOUT

150
9 Adding Support for Network Applications
9.3 DNS

RETRY_CFG

Synopsis: Specifies the number of retransmission tries.


Default: 4

RES_OPTIONS_CFG

Synopsis: Specifies the DNS Resolver Option Flags


Default: RES_DEFAULT

RES_DEFAULT is defined in resolv.h as follows:


#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)

The complete list of valid flags is defined in resolv.h as follows:


9
RES_INIT – address initialized
RES_DEBUG – print debug messages
RES_AAONLY – authoritative answers only
RES_USEVC – use virtual circuit
RES_PRIMARY – query primary server only
RES_IGNTC – ignore truncation errors
RES_RECURSE – recursion desired
RES_DEFNAMES – use default domain name
RES_STAYOPEN – keep TCP socket open
RES_DNSRCH – search up local domain tree
RES_INSECURE1 – type 1 security disabled
RES_INSECURE2 – type 2 security disabled
RES_NOALIASES – shuts off HOSTALIASES feature
RES_USE_INET6 – use/map IPv6 in gethostbyname( )
RES_NOTLDQUERY – do not query TLD names

NSCOUNT_CFG

Synopsis: Specifies the number of DNS name servers.


Default: 1

Increase this parameter value if you will query more than one DNS server.
This behavior can be helpful if the primary DNS server is unable to send a
reply.

151
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Domain Name Service Client Debug Output

The INCLUDE_DNS_RESOLVER_DEBUG component pulls in the res_debug


module. This component requires the INCLUDE_DNS_RESOLVER component and
contains the following configuration parameter:

DNS_DEBUG

Synopsis: Enables the display of DNS debug messages.


Default: FALSE

Setting DNS_DEBUG to TRUE prints a log of the resolver queries to the


console. Limit the use of this feature to a single task. If you are running
multiple tasks, the output to the console will be garbled.

9.4 SNTP
The Simple Network Time Protocol (SNTP) is a less complex form of the Network
Time Protocol (NTP) that does not require storing information about previous
communication. NTP is a protocol for synchronizing the clocks of computer
systems over packet-switched, variable-latency data networks. NTP uses UDP
port 123 as its transport layer.

Configuring VxWorks for SNTP

The Wind River Network Stack supports the following SNTP client and server
configuration components:

SNTP Client

SNTP Server
These components are listed under the
Network Components > Network Applications folder in Workbench.

152
9 Adding Support for Network Applications
9.4 SNTP

SNTP Client

The INCLUDE_SNTPC component pulls in the sntpcLib library.


Use sntpcTimeGet( ) to retrieve the current time from a remote SNTP/NTP server.
The sntpcTimeGet( ) routine reports the retrieved value to a format suitable for
POSIX-compliant clocks. To get time information, sntpcTimeGet( ) either sends a
request and extracts the time from the reply, or it waits passively until a message
is received from an SNTP/NTP server executing in broadcast mode. For more
information, see the sntpcTimeGet( ) reference entry.
The INCLUDE_SNTPC component requires the INCLUDE_BSD_SOCKET
component.
This component contains the following configuration parameter: 9

SNTPC_PORT

Synopsis: Port on client used for SNTP communication.


Default: 123 (the value specified by RFC 1769)

SNTP Server

The INCLUDE_SNTPS component includes an SNTP server implementation in a


VxWorks image. You can use an SNTP server to provide time information to other
systems. If the image includes the SNTP server, it automatically calls sntpsInit( )
during system startup.
This component requires the INCLUDE_BSD_SOCKET component.

Using SNTP

Depending on the value of the SNTP Server Mode Selection (set by the
configuration parameter SNTPS_MODE), the server executes either in
SNTP_PASSIVE or SNTP_ACTIVE mode. In SNTP_PASSIVE mode, the server waits
for requests from clients and sends replies containing an NTP timestamp. In
SNTP_ACTIVE mode, the server periodically transmits NTP timestamp
information at fixed intervals.
When executing in active mode, the SNTP server determines the target IP address
and broadcast interval using the configuration parameters:

SNTPS_DSTADDR – SNTP Server Destination Address

SNTPS_INTERVAL – SNTP Server Update Interval

153
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

By default, the server transmits the timestamp information to the local subnet
broadcast address every 64 seconds. To change these settings after system startup,
call the sntpsConfigSet( ) routine. The SNTP server operating in active mode can
also respond to client requests as they arrive.
The SNTP Client/Server Port (configuration parameter SNTP_PORT) assigns the
source and destination UDP port. The default port setting is 123 as specified by the
RFC 1769.
Finally, the SNTP server requires access to a reliable external time source. To do
this, you must provide a routine of the form:
STATUS sntpsClockHook (int request, void *pBuffer);

Until this routine is hooked into SNTP, the server cannot provide timestamp
information. There are two ways to hook this routine into the SNTP server. The
first is to configure VxWorks with the SNTPS Time Hook (configuration parameter
SNTPS_TIME_HOOK) set to the appropriate routine name. You can also call
sntpsClockSet( ). For more information, see the sntpsClockSet( ) reference entry.

! CAUTION: Hook routines, such as sntpsClockHook( ), must reside and execute


within the kernel domain.

SNTP Configuration Parameters

If you include INCLUDE_SNTPS, you can configure the SNTP Server at build time
using the following parameters:

SNPTS_MODE

Synopsis: Server mode, either SNTP_ACTIVE or SNTP_PASSIVE.


Default: SNTP_ACTIVE
Use this parameter to specify whether the server sends unsolicited update
messages.

SNTPS_PORT

Synopsis: Port used by server for SNTP communication.


Default: 123 (as specified by the RFC 1769)

154
9 Adding Support for Network Applications
9.5 FTP

SNTPS_DSTADDR

Synopsis: SNTP Server Destination Address.


Default: NULL
Use this parameter to specify the address of a recipient for active mode
updates. Use NULL to configure the server to broadcast the updates instead of
sending them to a particular recipient. A valid value for this parameter is any
quoted string containing an IP address expressed in dot notation.

SNTPS_INTERVAL

Synopsis: SNTP server update interval, in seconds.


Default: 64
9
Use this parameter to specify the number of seconds between the transmission
of SNTP update messages.

SNTPS_TIME_HOOK

Synopsis: SNTP time hook function, a clock access routine.


Default: NULL
A valid value for this parameter is of type FUNCPTR and must specify the
name of a clock access routine.

9.5 FTP
File Transfer Protocol (FTP) is the standard protocol for exchanging files over any
TCP/IP network. The FTP server is the computer that listens on the network for
connection requests from another computer. This computer is the FTP client, which
requests and connects to the FTP server, using FTP client software. The FTP client
can then manipulate files on the server, including uploading, downloading,
renaming, and deleting them.

155
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Configuring VxWorks for FTP

The Wind River Network Stack supports the following FTP client and server
configuration components usable for an FTP a client, a server, and anonymous
login:

FTP Client

FTPv6 Server Security
■ Anonymous FTP
■ FTP6 Client
■ FTP6 Server
These components are listed under the
Network Components > Network Applications folder in Workbench.

! CAUTION: If you build FTP to include the TELNET/FTP password protection


(INCLUDE_SECURITY) component, you should change the default username and
password to prevent unauthorized access from a source that is familiar with the
default Wind River login for TELNET and FTP. For information on changing the
username and password, see 9.11 Changing the Default Login for FTP, FTPv6, and
Telnet, p.173.

FTP Client

The INCLUDE_FTP component pulls in the ftpLib library and other modules that
implement the File Transfer Protocol (FTP) Client for IPv4. For information on the
functionality supplied by this configuration component, see the ftpLib reference
entry.
This component supplies the following configuration parameters:

FTP_DEBUG_OPTIONS

Synopsis: Enables the debugging facilities supplied by ftpLib.


Default: 0

FTP_TRANSIENT_MAX_RETRY_COUNT

Synopsis: Sets the maximum on retries in response to FTP_TRANSIENT.


Default: 100

156
9 Adding Support for Network Applications
9.5 FTP

FTP_TRANSIENT_RETRY_INTERVAL

Synopsis: Specifies the clock ticks between FTP_TRANSIENT retries.


Default: 0

FTP_TRANSIENT_FATAL

Synopsis: Specifies the FTP transient response evaluation function.


Default: ftpTransientFatal

The function specified here determines whether to retry a transmission that


generated a transient response. If you replace ftpTransientFatal with your
own function, your function must conform to the ftpTransientFatal prototype.
Consider the following sample ftpTransientFatal( ) function:
9
/************************************************************************
*
* ftpTransientFatal - determine whether to end FTP transient responses
*
* ftpXfer normally retries a command if the host responds with a 4xx
* reply. If this function is installed, it can immediately terminate
* the retry sequence.
*
* RETURNS
*
* TRUE - Terminate retry attempts
* FALSE - Continue retry attempts
*
*/

LOCAL BOOL ftpTransientFatal


(
UINT32 reply /* Three digit code defined in RFC #640 */
)
{
switch (reply)
{
case (421): /* Service not available */
case (450): /* File unavailable */
case (451): /* error in processing */
case (452): /* insufficient storage */
{
/* yes, these are actually non-recoverable replies */
return (TRUE);
break;
}
/* attempt to retry the last command */
default:
return (FALSE);
}
}

157
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

FTP_TIMEOUT

Synopsis: FTP client timeout on replies to commands sent to the server.


Default: 0

After sending a command to a server, an FTP client applies this timeout while
waiting for a reply. A value of zero defaults to FTP_REPLYTIMEOUTDEFAULT
(10 seconds).

FTPv6 Server Security

The INCLUDE_FTPD6_SECURITY component configures FTP server to require a


valid login before it grants access. This component requires the
INCLUDE_SECURITY component.

! CAUTION: If you include the FTPv6 server security (INCLUDE_FTPD6_SECURITY)


component, you should change the default username and password to prevent
unauthorized access from a source that is familiar with the default Wind River
login for TELNET and FTP. For information on changing the username password,
see 9.11 Changing the Default Login for FTP, FTPv6, and Telnet, p.173.

Anonymous FTP

The INCLUDE_FTPD6_GUEST_LOGIN component activates anonymous FTP (or


guest login) for a VxWorks target. This component requires the
INCLUDE_FTP6_SERVER component.
This component supplies the following configuration parameters:

FTPD6_GUEST_1

Synopsis: Identification for guest login.


Default: "/anonymous"

FTPD6_GUEST_2

Synopsis: Identification for guest login.


Default: "/anonymous"

158
9 Adding Support for Network Applications
9.5 FTP

FTPD6_GUEST_3

Synopsis: Identification for guest login.


Default: "/anonymous"

FTPD6_GUEST_ROOT_DIR

Synopsis: Root directory for guest access.


Default: "/anon"

FTPD6_GUEST_UPLOAD_DIR

Synopsis: Directory for guest uploads.


Default: "/anon"
9

FTPD6_GUEST_DIR_VALIDATE

Synopsis: Guest directory for validation flag, indicating whether or not to


validate the guest directories given.
Default: FALSE

FTP6 Client

The INCLUDE_FTP6 component pulls in the modules that implement the File
Transfer Protocol (FTP) Client for IPv6. Including this component pulls in the
ftp6Lib library. For information on the functionality supplied by this
configuration component, see the ftp6Lib reference entry.
The configuration parameter for this component is used as a parameter to the
ftpd6LibInit( ) call made from the network stack initialization code.
ftpd6LibInit (FTP6_REPLYTIMEOUT);

This component contains the following configuration parameter:

FTP6_REPLYTIMEOUT

Synopsis: Specifies the timeout, in seconds, on a reply from an FTP server.


Default: 10

159
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

FTP6 Server

The INCLUDE_FTP6_SERVER component pulls in the modules that implement a


File Transfer Protocol (FTP) Server for both IPv4 and IPv6. The FTP for IPv6 server
supports both active mode and passive mode. For information on the functionality
supplied by this configuration component, see the ftpd6Lib reference entry.
The configuration parameters for this component are used as parameters to the
ftpd6Init( ) call made from the network stack initialization code.
ftpd6Init (FTPD6_OPTIONS_STRING, FTPD6_LOGINRTN, FTPD6_SSIZE);

For information on the ftpd6Init( ) parameters, see the ftpd6Init( ) reference entry.
This component contains the following configuration parameters.

FTPD6_OPTIONS_STRING

Synopsis: String containing server options.


Default: "-6"

FTPD6_LOGINRTN

Synopsis: Expects the name of the user verification routine.


Default: NULL

FTPD6_SSIZE

Synopsis: Specifies the stack size for the primary server task.
Default: 0

9.6 TFTP
Trivial File Transfer Protocol (TFTP) is a simple file transfer protocol used to read
and write files to a remote server. TFTP has the functionality of a very basic form
of FTP; it uses a minimal amount of memory, cannot list directory contents, and
has no authentication or encryption mechanisms. Unlike FTP, which uses the TCP
transport layer protocol (port 21), TFTP uses the UDP (port 69) as its transport
protocol.

160
9 Adding Support for Network Applications
9.6 TFTP

Configuring VxWorks for TFTP

The Wind River Network Stack supports the following TFTP client and server
configuration components:

TFTP Client

TFTP Server
These components are listed under the
Network Components > Network Applications folder in Workbench.

TFTP Client

9
The INCLUDE_TFTP_CLIENT component pulls tftpLib and other modules that
implement the client side of the Trivial File Transfer Protocol (TFTP) for IPv4 and
IPv6. TFTP is implemented on top of the Internet User Datagram Protocol (UDP)
and conforms to the RFC 1350 recommendations for packet format.
Unlike FTP and RSH, TFTP requires no authentication; that is, the remote system
does not require an account or password. The TFTP client is able to access only
those files that the remote system considers publicly readable.
The TFTP client is useful at boot time, when you can use it to download a VxWorks
image from the boot host. For more information on the functionality associated
with this component, see the reference entry for tftpLib.
The INCLUDE_TFTP_CLIENT component has no configuration parameters and
requires the INCLUDE_BSD_SOCKET component.

NOTE: Changes to the TFTP client make it necessary that the application run at a
priority less than that of tNetTask. Otherwise, calls such as tftpXfer( ) will fail.
This change is consistent with the general advice that network applications should
run at a priority less than that of tNetTask. Previously, the TFTP client would
work even if it was running at a higher priority.

Transferring Files from a Remote Host

To help you transfer files from a remote TFTP host, this module supplies two
high-level interfaces: tftpXfer( ) and tftpCopy( ). For detailed information on these
routines, see the reference entry for tftpLib.

161
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

About Remote Host TFTP Servers

On a host running UNIX or some UNIX variant, the host-resident Internet daemon
starts the TFTP server. For added security, some hosts (for example, Sun hosts)
default to starting the TFTP server with the secure (-s) option enabled. If -s is
specified, the server restricts host access by rooting all TFTP requests into the
directory specified (for example, /tftpboot).
For example, if the secure option was set with -s /tftpboot, a TFTP request for the
file /vxBoot/vxWorks is satisfied by the file /tftpboot/vxBoot/vxWorks rather than
the expected file /vxBoot/vxWorks.
To disable the secure option on the TFTP server, edit /etc/inetd.conf and remove
the -s option from the tftpd entry.

TFTP Server

The INCLUDE_TFTP_SERVER component pulls in tftpdLib and other modules that


implement the server side of the Trivial File Transfer Protocol (TFTP) for IPv4 and
IPv6. TFTP is implemented on top of the Internet User Datagram Protocol (UDP)
and conforms to the RFC 1350 recommendations for packet format. The TFTP
server can be useful when a VxWorks target must supply boot images to an
X-Terminal or to another VxWorks target. For more information on the
functionality associated with this component, see the reference entry for tftpdLib.
The configuration parameters for this component are used as parameters to the
usrTftpdStart( ) call made from the network stack initialization code.
tftpdInit ( TFTP_SERVER_STACKSIZE,
TFTP_SERVER_DIRECTORYNAMES,
TFTP_SERVER_NOCONTROL,
TFTP_SERVER_MAXCONNECTIONS );

For information on how to use the parameters to this routine, see the
usrTftpdStart( ) reference entry. This component contains the following
configuration parameters.

TFTP_SERVER_STACKSIZE

Synopsis: Specifies the stack size for the tftpdTask.


Default: 0

The default of zero tells the system to use the internal default stack size, 12000.

162
9 Adding Support for Network Applications
9.7 RSH

TFTP_SERVER_DIRECTORYNAMES

Synopsis: Specifies the TFTP server directory names.


Default: "/tftpd1,/tftfp2"

TFTP_SERVER_NOCONTROL

Synopsis: TRUE indicates that no access control is required.


Default: FALSE

TFTP_SERVER_MAXCONNECTIONS

Synopsis: Specifies the maximum number of concurrent connections.


Default: 0
9
The default of zero tells the system to use the internal default, which is 10.

9.7 RSH
Rsh (remote shell) is a command-line program that executes shell commands as a
different user on a remote computer across a network. The remote system on
which the rsh executes needs to be running the rshd daemon.

Wind River Implementation

The Wind River Network Stack rsh implementation does not include an
equivalent to the rshd daemon. Thus, remote systems cannot use rsh to run
commands remotely on a Wind River Network Stack host.

Configuring VxWorks for rsh

The Wind River Network Stack supports the following rsh configuration
components:

Remote Command
This component is listed under the
Network Components > Network Applications folder in Workbench.

163
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Remote Command

The INCLUDE_REMLIB component pulls in remLib, the library that implements


the RSH protocol for VxWorks. Using this RSH implementation, a VxWorks target
can execute commands on remote systems that run an rshd shell server. The
command results return on standard output and standard error over socket
connections. This library also supports rcmd_af( ), which supports both IPv4 and
IPv6.
The configuration parameter for this component is used as a parameter to the
remLibInit( ) call made from the network stack initialization code.
remLibInit (RSH_STDERR_SETUP_TIMEOUT);

This component contains the following configuration parameter:

RSH_STDERR_SETUP_TIMEOUT

Synopsis: The timeout (if any) on the wait for a remote response.
Default: -1

Use this parameter to specify how long an rcmd( ) call should wait for a return
from its internal call to select. The default value for this parameter is -1, which
is no timeout or WAIT_FOREVER.
For more information on how to use RSH under the Wind River Network Stack,
see the remLib reference entries.

Enabling Access to an RSH User

Included in an RSH request is the name of the requesting user. The receiving host
can then honor or ignore the request based on the user name and the site from
which the request originates. How you set up a receiving system to allow access to
particular users and sites depends on the specifics of the receiving system’s OS and
networking software.
For Windows hosts, support for RSH is determined by your version of Windows
and the networking software you are using. See that documentation for details.
For UNIX hosts running the BSD rshd, an RSH request is honored only if it
originated on a known system by a user with local login privileges (although you
can use the -l (dash el) option to configure the BSD rshd to omit this verification).
The list of known systems is specified in either of two locations. The first location,
the /etc/hosts.equiv file (UNIX) or the /etc/hosts.allow file (LINUX), maintains a
list of all systems from which remote access is allowed for all users that have local

164
9 Adding Support for Network Applications
9.8 RPC

accounts. The second location, a ~userName/.rhosts file, maintains a list of systems


from which remote access is allowed for that particular user, userName.
Which location you use depends on your security needs. In most environments,
adding system names to the /etc/hosts.equiv file is considered too dangerous.
Thus, for most environments, the preferred method is to add system names to a
~userName/.rhosts file. The format for this file is one system name per line.

9.8 RPC
9
The Remote Procedure Call (RPC) protocol, as specified by RFC 1831, is a protocol
that allows a process on one machine to call a procedure that is executed by
another process on another machine. It implements a client-server model of task
interaction. In this model, client tasks request services of server tasks and then wait
for replies. RPC formalizes this model and provides a standard protocol for
passing requests and returning replies.

9.8.1 Wind River Implementation of RPC

The Wind River RPC implementation is based on a public domain implementation


that originated at Sun Microsystems. The Wind River RPC implementation is
compliant with the Sun Open Network Computing (ONC) RPC. The Open
Software Foundation has Distributed Computing Environment (DCE) which has
its own RPC implementation. Using RPC, a VxWorks task or host machine process
can invoke routines that are executed on other VxWorks or host machines, in any
combination. For more information, see RFC 1831 and the reference entry for
rpcLib and 9.8 RPC, p.165.
When working with the Wind River RPC implementation (a kernel-only
implementation), keep in mind that it is task-specific. Each task must call
rpcTaskInit( ) before making any RPC-related calls.

165
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

9.8.2 Configuring VxWorks for RPC

The Wind River Network Stack supports the following RPC configuration
components:

RPC

XDR

XDR Boolean Support
These components are listed under the
Network Components > Network Applications > RPC Components folder in
Workbench.

RPC

The INCLUDE_RPC component pulls in rpcLib and other modules that implement
the Remote Procedure Call (RPC) protocol. For information on the externally
callable functions associated with the modules in this component, see the rpcLib
reference entry.

XDR

The INCLUDE_XDR component pulls in modules that implement generic XDR


(External Data Representation) routines as described in RFC 1014. There are no
externally callable functions or configuration parameters associated with this
component.

XDR Boolean Support

The INCLUDE_XDR_BOOL_T component pulls in modules that supply the XDR


routine for bool_t’s. There are no externally callable functions or configuration
parameters associated with this component.

166
9 Adding Support for Network Applications
9.9 RLOGIN

9.9 RLOGIN
RLOGIN allows remote access to and from a target. The Wind River
implementation of RLOGIN supports both IPv4 and IPv6.

Configuring VxWorks for RLOGIN

The Wind River Network Stack supports the following RPC configuration
components:

RLOGIN
This component is listed under the 9
Network Components > Network Applications folder in Workbench.

RLOGIN

The INCLUDE_RLOGIN component pulls in rlogLib, a library that provides


rlogin( ), a remote login facility (both the client and the server side). This
component requires the INCLUDE_NET_HOST_SETUP component.
Using the client, you can log in to a host system from a VxWorks terminal. Using
the server, you can log in to VxWorks from a host system. For more information
on the Wind River Network Stack implementation of rlogin( ), see the reference
entry for rlogLib.

Connecting to Host Systems

When connecting with a Windows host system, the ability of VxWorks to remotely
login depends on your version of Windows and the networking software you are
using. See that documentation for details.
When connecting with a UNIX host system, access permission must be granted to
the VxWorks system by entering its system name either in the .rhosts file (in your
home directory) or in the /etc/hosts.equiv file. For more information, see Enabling
Access to an RSH User, p.164.

167
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Using RLOGIN in an RTP

Because this application must interact with a user, it requires the active shell to be
locked to access standard IO. The shellLock( ) API is not supported for use in an
RTP. Thus, instead of using rtpSp( ), you launch the client through a shell
command interpreter. To do this, make sure that the image includes:

INCLUDE_SHELL_INTERP_CMD
■ INCLUDE_SHELL_INTERP_C
In a target shell for such an image, you can type:
-> cmd
# rlogin.vxe "10.34.10.21"

This opens a remote login session on 10.34.10.21.

9.10 Telnet
Telnet is an application protocol that provides command-line login sessions
between hosts on a network. The Wind River implementation of telnet supports
both IPv4 or IPv6.

Configuring VxWorks for Telnet

The Wind River Network Stack supports the following telnet configuration
components:
■ Telnet Server
■ Telnet Client

TELNET/FTP password protection
These components are listed under the
Network Components > Network Applications folder in Workbench.

168
9 Adding Support for Network Applications
9.10 Telnet

! CAUTION: If you include the TELNET/FTP password protection


(INCLUDE_SECURITY) component, you should change the default username and
password to prevent unauthorized access from a source that is familiar with the
default Wind River login for TELNET and FTP. For information on changing the
username and password, see 9.11 Changing the Default Login for FTP, FTPv6, and
Telnet, p.173.

Telnet Server

The INCLUDE_TELNET component pulls in telnetdLib, a software module that


implements a telnet server for VxWorks. The telnet server is a utility that supports
9
remote login to a VxWorks target. In that, it is similar to rlogin. However, telnet
differs from rlogin in that telnet does not require any previous setup of .rhosts file
or its equivalent. The only thing required on the remote system is that it is
configured to grant login privileges to the user trying to use that system as the base
from which to login to a VxWorks target.
For more information on the API associated with this component, see the reference
entry for telnetdLib.
The INCLUDE_TELNET component requires the INCLUDE_BSD_SOCKET
component.
This component contains the following configuration parameters:

TELNETD_MAX_CLIENTS

Synopsis: The maximum number of simultaneous client sessions.


Default: 1

TELNETD_TASKFLAG

Synopsis: Lets the server create tasks before establishing connections.


Default: FALSE

TELNETD_PORT

Synopsis: The port monitored by the telnet server.


Default: 23

169
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

TELNETD_PARSER_HOOK

Synopsis: The command interpreter to use with the telnet server.


Default: shellParserControl
This configuration component expects the name of the routine that
implements the command interpreter for use with telnet. The default is the
kernel shell, shellParserControl( ). This routine, defined in
shellRemoteAccessLib is private. If you have written or ported an application
that requires you to replace shellParserControl( ) with your own
implementation, you must do so using a routine with the same API.
That API is:
STATUS shellParserControl
(
UINT32 remoteEvent, /* Starting or stopping a connection? */
UINT32 sessionId, /* Unique identifier for each session */
UINT32 slaveFd /* File descriptor for character i/o */
VOIDFUNCPTR logoutFunc /* Routine executed at log out. */
)

The internal (not printed) reference entry for shellParserControl( ) is as


follows:
shellParserControl - handle connecting and disconnecting remote users
This routine configures the shell to connect new telnet or rlogin sessions
to the command interpreter by redirecting standard input and standard
output and restores the original settings when those sessions exit. This
routine is the default parser control installed as part of the
INCLUDE_SHELL component. The default TELNETD_PARSER_HOOK
setting for the INCLUDE_TELNET component accesses this routine.
After VxWorks 6.0, multiple sessions are supported. However, in the 5.n
versions, VxWorks supports only one remote session at a time, which
determines the default value of the TELNETD_MAX_CLIENTS parameter.
RETURNS: OK or ERROR.

! WARNING: Because shellParserControl( ) is not a public API, it can change from


release to release, as it did between VxWorks 5.5.1 and 6.0. If you replace
shellParserControl( ), you must test its forward compatibility with subsequent
releases of VxWorks and the network stack.

170
9 Adding Support for Network Applications
9.10 Telnet

Telnet Client

The INCLUDE_TELNET_CLIENT component pulls in the telnettcLib module and


the VxWorks telnet client, a lightweight RTP-compatible implementation of the
client side of the Telnet Protocol (RFC 854). This client supports both IPv4 and
IPv6, provides all the essential features of NVT (Network Virtual Terminal), and
can function as an interface between terminal and terminal-oriented processes.

NOTE: By default, the client sends an ECHO at start up. It works in default mode
only when it receives DO and DONOT from a remote telnet server.

TELNET/FTP password protection 9

The INCLUDE_SECURITY component pulls in loginLib, which provides


TELNET/FTP password protection. This component depends on the global
variables LOGIN_USER_NAME and LOGIN_PASSWORD to supply a user name
and a password for that user name.
This component contains the following configuration parameters:

LOGIN_PASSWORD

Synopsis: RLOGIN/telnet encyrpted password.


Default: "RcQbRbzRyc"

LOGIN_USERNAME

Synopsis: RLOGIN/telnet username.


Default: "target"

Using Telnet in an RTP

Because this application must interact with a user, it requires the active shell to be
locked to access standard IO. The shellLock( ) API is not supported for use in an
RTP. Thus, instead of using rtpSp( ), you should launch the client through a shell
command interpreter. To do this, make sure that the image you build includes the
components:

INCLUDE_SHELL_INTERP_CMD

INCLUDE_SHELL_INTERP_C

171
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

In a target shell for such an image, you can type:


-> cmd
# telnet.vxe "10.34.10.21"

This opens a telnet session on 10.34.10.21.

Unsupported Commands and Options

The VxWorks telnet client can decode commands (ICA) sent from a remote host,
but, for the most part, it does not process them. Table 9-1 lists the unsupported
commands.

Table 9-1 Unsupported Telnet Client Commands

Name Code Meaning

SE 240 End of subnegotiation parameters.

NOP 241 No operation.

Data Mark 242 The data stream portion of a Synch. This should
always be accompanied by a TCP Urgent notification.

Break 243 NVT character BRK.

Interrupt Process 244 The function IP.

Abort output 245 The function AO.

Are You There 246 The function AYT.

Erase character 247 The function EC.

Erase Line 248 The function EL.

SB 250 Indicates that what follows is subnegotiation of the


indicated option.

WILL option code 251 Indicates the desire to begin performing, or


confirmation that you are now performing, the
indicated option.

DO option code 253 Indicates the request that the other party perform, or
confirmation that you are expecting the other party to
perform, the indicated option.

172
9 Adding Support for Network Applications
9.11 Changing the Default Login for FTP, FTPv6, and Telnet

Table 9-1 Unsupported Telnet Client Commands (cont’d)

Name Code Meaning

DON'T option code 254 Indicates the demand that the other party stop
performing, or confirmation that you are no longer
expecting the other party to perform, the indicated
option.

The VxWorks implementation of the send command supports only the ECHO and
TERMINALTYPE options. Not supported are the following send options:

3270 REGIME NAME RCP


AUTHENTICATION NAOCRD RCTE
9
BINARY NAOFFD SEND LOCATION
BYTE MACRO NAOHTD STATUS
DATA ENTRY TERMINAL NAOHTS SUPDUP
ENCRYPT NAOL SUPDUP OUTPUT
END OF RECORD NAOLFD SUPPRESS GO AHEAD
EXTEND ASCII NAOP TACACS UID
LFLOW NAOVTD TIMING MARK
LINEMODE NAOVTS TSPEED
NAWS TTYLOC
NEW-ENVIRON X.3 PAD
OLD-ENVIRON XDISPLOC
OUTPUT MARKING

9.11 Changing the Default Login for FTP, FTPv6, and Telnet
VxWorks provides a default user name and password for logging in to FTP,
FTPv6, and Telnet. If you enable security for these applications, you should reset
the user name and password to prevent unauthorized access from a source that is
familiar with the default values. In building these applications, security is enabled
when you include either of the following build components:

For FTP and Telnet: TELNET/FTP password protection (INCLUDE_SECURITY)

For FTPv6: FTPv6 server security (INCLUDE_FTPD6_SECURITY)
FTPv6 server security (INCLUDE_FTPD6_SECURITY)

173
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

9.11.1 Changing the Default Login Before You Build VxWorks

Before you build, you can change the login user name and password in the
configAll.h file or from within Workbench. In both cases, you first need to obtain
an encrypted version of the password you want to use.
After you build, you can change the user name and password from the VxWorks
development shell. In this case, you need to first obtain an encrypted version of the
password.

Obtaining an Encrypted Password

To obtain an encrypted password:


1. From the VxWorks development shell command line, go to the BSP directory
for your build:
installDir/vxworksDir/target/config/bspDir
2. Enter the command vxencrypt, as in the following example:
installDir/vxworks-6.3/target/config/wrSbc8560> vxencrypt
The system prompts for a password:
please enter password:
3. Enter a password, from 8 to 40 characters in length, that you want encrypted.
The system returns your encrypted password, as in the following example:
encrypted password is RQbebQRyy

Changing the user name and password in configAll.h

To change the user name and password in the configAll.h file:


1. Obtain an encrypted password, as described in the preceding section.
2. Open the file configAll.h for editing.
The location of the file is:
installDir/vxworksDir/target/config/all/configAll.h

174
9 Adding Support for Network Applications
9.11 Changing the Default Login for FTP, FTPv6, and Telnet

3. To change the default login user name, locate the following line and replace
target with the user name of your choice:
#define LOGIN_USER_NAME "target"
4. To change the default login password, locate the following line and replace
RcQbRbzRyc with the encrypted password you obtained at Step 1:
#define LOGIN_PASSWORD "RcQbRbzRyc" /* "password" */

Changing the user name and password in Workbench

To change the login user name and password in Workbench:


9
1. Obtain an encrypted password, as described in Obtaining an Encrypted
Password, p.174.
2. Locate and expand the build component TELNET/FTP password protection
in the Workbench component tree, under Network
Components > Network Applications.
Figure 9-1 shows the component as it appears when expanded:

Figure 9-1 TELNET/FTP password protection parameters (user name and password)

3. Replace the password parameter value, RcQbRbzRyc, with the encrypted


password you obtained at Step 1.
4. Replace the user name parameter value, target, with the user name of your
choice.

9.11.2 Changing the Default Login After You Build VxWorks

To change the default login user name and password after building VxWorks:
1. Obtain an encrypted password, as described in Obtaining an Encrypted
Password, p.174.

175
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

2. From the VxWorks development shell command line, delete the default login
values, target and password, as follows:
loginUserDelete "target", "password"
3. Enter new login values, as follows:
loginUserAdd "username", "password"
where password is the encrypted password you obtained at Step 1.

9.12 Creating a netDrv Device for RSH or FTP


The Wind River Network Stack provides an implementation of the client side (but
not the server side) of the RSH protocol. The Wind River Network Stack also
provides an implementation of both the client and the server sides of the FTP
protocol.
Using RSH, a VxWorks application can run commands on a remote system and
receive the command results on standard output and standard error over socket
connections. To execute commands remotely, RSH requires that the remote system
supports the server side of RSH and that the remote system grant access privileges
to the user specified in the RSH request. On a UNIX system, RSH server support is
implemented using the rshd shell daemon, and access privileges are controlled by
a .rhosts file. On a Wind River Network Stack host, there is no equivalent to rshd.
Thus, remote systems cannot use RSH to run commands on a Wind River
Network Stack host.
You can use both RSH and FTP directly, but you can also use them indirectly to
download files through the mediation of the netDrv driver. Using netDrv in this
way is especially convenient when a target needs to download a run-time image at
boot time.
That netDrv can use FTP to download a file is not surprising, given that FTP is a
protocol designed specifically for file transfer. Specifically, netDrv uses the FTP
RETR and STOR commands to retrieve and store the entire requested file. That
netDrv can use RSH to download a file is less obvious. RSH has no built-in
commands dedicated to file transfer. However, netDrv executes a remote cat on
the file it wants to download.

176
9 Adding Support for Network Applications
9.12 Creating a netDrv Device for RSH or FTP

Setting the User ID for Remote File Access with RSH or FTP

All FTP and RSH requests to a remote system include the user name. All FTP
requests include a password as well as a user name. From VxWorks, you can
specify the user name and password for remote requests by calling iam( ):
iam ("username", "password");

The first argument to iam( ) is the user name that identifies you when you access
remote systems. The second argument is the FTP password. This is ignored if RSH
is being used, and can be specified as NULL or 0 (zero).
For example, the following command tells VxWorks that all accesses to remote
systems with RSH or FTP are through user darger, and if FTP is used, the password
is unreal: 9
-> iam "darger", "unreal"

NOTE: When a VxWorks boot program downloads a run-time image from a


remote network source using a netDrv instance, it relies upon either the FTP or
RSH protocols. To determine its user name and password (if any) for use with
these protocols, the boot program relies upon the values specified for these
parameters in the boot line.

Setting File Permissions on the Remote System

For a VxWorks system to have access to a particular file on a host, you must set up
permissions on the host system appropriately. The user name seen from the host
must have permission to read that file (and write it, if necessary). That user name
must also have permission to access all directories in the path. The easiest way to
check this is to log in to the host with the user name VxWorks uses, and try to read
or write the file in question. If you cannot do this, neither can the VxWorks system.

Creating a netDrv Instance

Although you can use netDrv at boot time to download a run-time image, netDrv
is not limited to boot time or run-time images. It is a generic I/O device that you
can use to access files on a remote networked system. To include netDrv, use the
INCLUDE_NET_DRV configuration component.

177
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

To use netDrv, you must create a netDrv instance for each system on which you
want to access files. You can then use this device in standard VxWorks I/O device
calls such as open( ), read( ), write( ), and close( ). To create a netDrv device, call
netDevCreate( ):
netDevCreate ("devName", "host", protocol);

Its arguments are:


devName
The name of the device to be created.
host
The Internet address of the host in dot notation, or the name of the remote
system as specified in a previous call to hostAdd( ). Most typically, one
composes the device name using the host name followed by a colon.
protocol
The file transfer protocol: 0 for RSH or 1 for FTP.
For example, the following call creates a new I/O device on VxWorks called mars:,
which accesses files on the host system mars using RSH:
-> netDevCreate "mars:", "mars", 0

After a network device is created, files on that host are accessible by appending the
host pathname to the device name. For example, the filename
mars:/usr/darger/myfile refers to the file /usr/darger/myfile on the mars system.
You can read or write to this file as if it were a local file. For example, the following
shell command opens that file for I/O access:
-> fd = open ("mars:/usr/darger/myfile", 2)

The VxWorks network startup routine, usrNetInit( ) in usrNetwork.c,


automatically creates a network device for the host name specified in the VxWorks
boot parameters. If no FTP password was specified in the boot parameters, the
network device is specified with the RSH protocol. If a password was specified,
FTP is used.

Using netDrv to Download Run-Time Images

The usrNetInit( ) call in a VxWorks boot program can automatically create a


netDrv instance for the host name specified in the VxWorks boot parameters. The
boot program then uses this device to download an image from the host specified
in the boot parameters. Whether the netDrv instance uses FTP or RSH to
download the image depends on whether the boot parameters include an FTP

178
9 Adding Support for Network Applications
9.12 Creating a netDrv Device for RSH or FTP

password. When the FTP password is present, netDrv uses FTP. Otherwise,
netDrv uses RSH.4
Consider the system shown in Figure 9-2. Using a network connection, CPU 1 can
use FTP to download its run-time image from the storage device accessible
through CPU 0. Note that the client must include a non-empty ftp password field
in its boot parameter.
Including an FTP password tells netDrv to use FTP. Whether the FTP server on
CPU 0 checks the validity of the password depends on whether the FTP server on
CPU 0 has been configured with security turned off (the default) or on. The
relevant configuration component is INCLUDE_FTPD6_SECURITY.
The FTP server daemon is initialized on the VxWorks server based on the
configuration. The relevant configuration parameter is INCLUDE_FTP6_SERVER. 9
See also the reference entry for ftpd6Lib.

Figure 9-2 FTP Boot Example

/sd0/vx2 CPU 0 CPU 1

vxServer vxClient

Disk
10.27.0.1 10.27.0.2

4. When creating a boot program that must download an image using an RSH or an FTP client,
you must make sure that you include those components in the program.

179
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

180
10
Working with DHCPv4
and DHCPv6

10.1 Introduction 181


10.2 Configuring VxWorks for DHCPv4 182
10.3 Working with the DHCPv4 Client 190
10.4 Working with the DHCPv4 Relay Agent 192
10.5 Working with the DHCPv4 Server 195
10.6 Using DHCPv6 200

10.1 Introduction
The purpose of the BOOTP, DHCP, and DHCPv6 protocols is to provide a
mechanism by which a host can retrieve configuration parameters (in particular,
an IP address) from a remote server. The Wind River Network Stack includes a
DHCP client, server, and relay agent. Both the client and server implementations
support all options described in RFC 2132.
The DHCP (RFC 2131) protocol is the successor to BOOTP, and an extension of it,
designed to supply clients with all of the Internet configuration parameters
defined in the Host Requirements documents (RFC 1122 and RFC 1123) without
manual intervention. As such, DHCP can provide all that BOOTP provides and

181
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

more. In fact, the RFCs for DHCP require that the server handle requests (see RFC
2132) from BOOTP clients. For this reason, although the Wind River
Network Stack includes a BOOTP implementation, ongoing developments will be
addressed in DHCP and not BOOTP.
This chapter provides per-component descriptions of all the components
associated with the Wind River DHCPv4 and DHCPv6 implementations.
Currently, the standard VxWorks boot program supports IPv4 but not IPv6,
although it can download a run-time image that does support IPv6.

10.2 Configuring VxWorks for DHCPv4


Like BOOTP, DHCP allows the permanent allocation of configuration parameters
to specific clients. DHCP also supports the assignment of a network address for a
finite lease period. This feature allows the serial reassignment of network
addresses to different clients. This feature is useful when IP addresses are limited
and the clients connect to the network for limited periods, such as is usually the
case with clients that connect to the network over a modem.

10.2.1 DHCPv4 Component Summary

The Wind River Network Stack supports the following DHCPv4 configuration
components:

DHCPv4 Run-time Client

DHCPv4 Boot-Time Client

DHCPv4 Client Timestamp Storage

DHCPv4 Client Lease Verification/Assignment

DHCPv4 Client Common Library

DHCP Client Show Routines

DHCP Server

DHCP Relay Agent

DHCP Shared Files for Server and Relay Agent

DHCP Core files
These components are all listed under the
Network Components > Network Applications > DHCP Components folder in
Workbench.

182
10 Working with DHCPv4 and DHCPv6
10.2 Configuring VxWorks for DHCPv4

DHCPv4 Run-time Client

The INCLUDE_DHCPC component implements the DHCP client, which can


retrieve configuration parameters from either a DHCP or BOOTP server. The
DHCP client can hold only a single lease; it does not support multiple concurrent
leases. Including he INCLUDE_DHCPC component in an image automatically sets
up a call to usrDhcpcStart( ), which is dependent upon code supplied in the
configlettes, net/coreip/apps/usrNetDhcpcCfg.c, and net/coreip/usrNetBoot.c.

NOTE: The asynchronous use of DHCP requires that you provide an event hook
routine to handle lease events. For more information, see the
dhcpcEventHookAdd( ) reference entry.

This component requires the following configuration components:


10
■ INCLUDE_IPV4
■ INCLUDE_BSD_SOCKET
■ INCLUDE_DOMAIN_INIT
Including INCLUDE_DHCPC excludes INCLUDE_BOOTP. For information on the
externally callable routines associated most centrally with this component, see
dhcpcLib.

NOTE: This component pulls in the standard DHCP client for use in the image
loaded by a boot program. It is not the reduced DHCP client implementation
designed for use in a boot program. That reduced client is associated with the
INCLUDE_DHCPC_BOOT component. See DHCPv4 Boot-Time Client, p.185.

The INCLUDE_DHCPC component contains the configuration parameters listed


below. When setting values for the parameters supplied by this component, keep
in mind that the DHCP client rejects all offers whose duration is less than the
minimum lease. Therefore, setting the DHCP Client Minimum Lease value too
high can prevent the retrieval of any configuration parameters.

DHCPC_CPORT

Synopsis: Specifies the port monitored by DHCP clients.


Default: 68

DHCPC_DEFAULT_LEASE

Synopsis: Specifies default lease length for a DHCP client, in seconds.


Default: 3600

183
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCPC_MAX_LEASES

Synopsis: Specifies the maximum number of concurrent leases.


Default: 4

This limit on multiple concurrent leases includes a lease established at boot


time.

DHCPC_MAX_MSGSIZE

Synopsis: Specifies the maximum size (in bytes) for a DHCP message.
Default: 590

The default DHCPC_MAX_MSGSIZE value is the minimum-sized DHCP


message in an Ethernet frame.

DHCPC_MIN_LEASE

Synopsis: Specifies the minimum acceptable lease length (in seconds).


Default: 30

Keep in mind that the DHCP client rejects all offers whose duration is less than
the minimum lease. Therefore, setting the DHCP Client Minimum Lease value
too high could prevent the retrieval of any configuration parameters.

DHCPC_OFFER_TIMEOUT

Synopsis: Seconds to wait for multiple lease offers.


Default: 5

DHCPC_SPORT

Synopsis: Port monitored by DHCP servers.


Default: 67

DHCPC_DISCOVER_RETRIES

Synopsis: DHCP client discover retry limit, specifies the maximum number
of DHCPDISCOVER attempts before timeout.
Default: 67

184
10 Working with DHCPv4 and DHCPv6
10.2 Configuring VxWorks for DHCPv4

DHCPv4 Boot-Time Client

The INCLUDE_DHCPC_BOOT component is part of a boot ROM build. It provides


a striped down version of the DHCP client that is used for obtaining boot
parameters, network information, and an IP address. Including this component
excludes the INCLUDE_BOOTP component.
The INCLUDE_DHCPC_BOOT component does not include a function for releasing
an address lease or handling the lease expiry. It is assumed that any IP address
lease given by a DHCP server will have a lease time longer than the time required
for the target to complete booting. For more information, see the dhcpcBootLib
reference entry.
INCLUDE_DHCPC_BOOT contains the following configuration parameters:

DHCPC_CPORT 10

Synopsis: Port monitored by DHCP clients.


Default: 68

DHCPC_DEFAULT_LEASE

Synopsis: Desired lease length in seconds.


Default: 3600

DHCPC_MAX_MSGSIZE

Synopsis: Default allows minimum DHCP message in Ethernet frame.


Default: 590

DHCPC_MIN_LEASE

Synopsis: Acceptable lease duration in seconds.


Default: 30

DHCPC_OFFER_TIMEOUT

Synopsis: Interval for collecting server lease offers, in seconds.


Default: 5

DHCPC_SPORT

Synopsis: Port monitored by DHCP servers.


Default: 67

185
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCPv4 Client Timestamp Storage

The INCLUDE_DHCPC_LEASE_SAVE component implements the DHCPv4 client


timestamp storage mechanism, which saves lease timestamp information in an
address field.
When you include the INCLUDE_DHCPC_LEASE_SAVE component,
usrDhcpcLeaseSave( ) is automatically called, and the VxWorks image prepares a
boot string that contains timestamp information for a new DHCP lease established
or verified during the run-time startup. That boot string is then written to
BOOT_LINE_ADRS, a BSP configuration parameter.
The INCLUDE_DHCPC_LEASE_SAVE component requires the following
components:
■ INCLUDE_DHCPC
■ INCLUDE_NET_INIT

DHCPv4 Client Lease Verification/Assignment

The INCLUDE_DHCPC_LEASE_TEST component enables the DHCPv4 client to


inspect the boot line during its initialization. If the boot line contains DHCPv4
lease information, the client attempts to renew the lease. If there is no lease
information in the boot line, and, if the boot line does not contain a manually
entered IP address, including this component configures the DHCP client to
negotiate with the server for a new lease. Including this component automatically
sets up a boot-time call to usrDhcpcLeaseTest( ).
The INCLUDE_DHCPC_LEASE_TEST component requires the following
components:
■ INCLUDE_DHCPC
■ INCLUDE_NET_INIT

DHCPv4 Client Common Library

The INCLUDE_DHCPC_SHARE component pulls in dhcpcCommonLib, which


provides externally callable routines for adding an option to the request list and
for setting its value. For more information, see the dhcpcCommonLib reference
entry.

186
10 Working with DHCPv4 and DHCPv6
10.2 Configuring VxWorks for DHCPv4

DHCP Client Show Routines

The INCLUDE_DHCPC_SHOW component pulls in dhcpcShow, a software


module that implements show functionality for the DHCP client. dhcpcShow
provide externally callable routines for displaying information on the lease timers
and lease parameters. For more information, see the dhcpcShow reference entry.

DHCP Relay Agent

The INCLUDE_DHCPR component pulls in dhcprLib and other modules that


implement the DHCP relay agent. The DHCP relay agent provides forwarding of
DHCP and BOOTP messages across subnet boundaries.
The relay agent forwards DHCP messages between clients and servers resident on
10
different subnets. A DHCP server, if present on a subnet, can also forward
messages across subnet boundaries. Thus, a relay agent is needed only if there is
no DHCP server running on the subnet.
The INCLUDE_DHCPR component requires the INCLUDE_IPV4 component.
There are no configuration parameters defined exclusively for this component.
Instead, it uses the values that you specify in INCLUDE_DHCPS_SHARE for:
■ DHCPS_MAX_MSGSIZE

DHCPS_CPORT

DHCPS_SPORT

DHCP_MAX_HOPS

DHCP Shared Files for Server and Relay Agent

The INCLUDE_DHCPS_SHARE component pulls in additional software modules


required for the DHCP relay agent.
This component contains the following configuration parameters:

DHCPS_MAX_MSGSIZE

Synopsis: Maximum message size for the DHCP server or relay agent.
Default: 590

The default value allows for a minimum DHCP message in an Ethernet frame.

187
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCPS_CPORT

Synopsis: The target port monitored by DHCP clients.


Default: 68

DHCPS_SPORT

Synopsis: The host port monitored by DHCP servers and relay agents.
Default: 67

DHCP_MAX_HOPS

Synopsis: Maximum hop count before discarding a message.


Default: 4

This value limits the number of subnets that a DHCP message can cross
(prevents network flooding). The maximum valid value is 16.

DHCP Server

The INCLUDE_DHCPS component pulls in modules that implement the DHCP


server. Including INCLUDE_DHCPS sets up an automatic call to usrDhcpsStart( ),
which is defined in net/coreip/apps/usrNetDhcpsCfg.c. The Wind River Network
Stack DHCP server can process both BOOTP and DHCP messages.
Including INCLUDE_DHCPS requires INCLUDE_DHCPS_SHARE and
INCLUDE_IPV4. It also necessarily excludes INCLUDE_DHCPR, the relay agent.
The externally callable routines associated with this component are described in
the dhcpsLib reference entry.
The INCLUDE_DHCPS component defines a few configuration parameters locally.
It also depends on the following parameters specified specify in
INCLUDE_DHCPS_SHARE for:

DHCPS_MAX_MSGSIZE

DHCPS_CPORT

DHCPS_SPORT

DHCP_MAX_HOPS
Use the locally defined configuration parameters as follows:

188
10 Working with DHCPv4 and DHCPv6
10.2 Configuring VxWorks for DHCPv4

DHCPS_ADDRESS_HOOK

Synopsis: The name of a function for preserving runtime pool entries.


Default: NULL

This parameter lets you specify the name of an optional storage routine. For
more information, see Storing and Retrieving Active Network Configurations,
p.198.

DHCPS_DEFAULT_LEASE

Synopsis: The default lease length in seconds.


Default: 3600

This constant specifies the default lease length in seconds. This value applies
if no explicit value is set in the address pool.
10
DHCPS_LEASE_HOOK

Synopsis: The name of the function that stores active leases.


Default: NULL

This constant specifies the name of the routine that handles non-volatile
storage of the active leases. For more information, see Storing and Retrieving
Active Network Configurations, p.198

DHCP Core files

The INCLUDE_DHCP_CORE component pulls in the DHCP common routines. This


component requires the INCLUDE_BPF configuration component and has no
parameters.

10.2.2 Interface Settings Retrieved Using DHCPv4

If the server is configured to provide them, a lease can include configuration


parameters in addition to an assigned IP address. To minimize network traffic, the
DHCP client sets configuration values to the defaults specified in the Host
Requirements documents (RFC 1122 and RFC 1123) if the server does not specify
values for the corresponding parameters.
Unlike the configuration parameters supplied by BOOTP, the DHCP-assigned
configuration parameters can expire. Although a DHCP server can duplicate
BOOTP behavior and issue a permanent IP address to the client, the lease granted

189
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

is usually temporary. To continue using the assigned parameters, the client must
periodically contact the issuing server to renew the lease.

! WARNING: The Wind River development tools do not currently have any way to
discover or respond to a change in the target’s IP address. Such a change breaks the
network connection. In response, you must manually reconnect the tools to the
target’s new IP address. During development, this is rarely a serious problem, and
you can avoid it by having the DHCP server issue an infinite lease on the target’s
IP address.

10.3 Working with the DHCPv4 Client


The target-resident DHCPv4 client can retrieve configuration information either
synchronously or asynchronously. In addition, the retrieved network
configuration information can be applied directly to the underlying network
interface or used for some other purpose. The following example demonstrates the
synchronous execution of a DHCPv4 request for a lease with a 30-minute duration
in which the retrieved configuration parameters are applied to the network
interface used to contact the DHCPv4 server.
unsigned long duration;

pIf = ifunit ("net0"); /* Access network device. */

/* Initialize lease variables for automatic configuration. */

pLeaseCookie = dhcpcInit (pIf, TRUE);


if (pLeaseCookie == NULL)
return (ERROR);

/* Set any lease options here. */

duration = htonl( 1800 );


dhcpcOptionAdd (pLeaseCookie, _DHCP_LEASE_TIME_TAG,4,(UCHAR*)&duration);

result = dhcpcBind (pLeaseCookie, TRUE); /* Synchronous execution. */


if (result != OK)
return (ERROR);

In the code above, the dhcpcInit( ) call used a value of TRUE for the autoconfig
parameter. This automatically includes a request for a subnet mask and broadcast
address in the cookie (pLeaseCookie). To request additional options for this lease
the code makes a call to dhcpcOptionAdd( ). Because the DHCPv4 protocol

190
10 Working with DHCPv4 and DHCPv6
10.3 Working with the DHCPv4 Client

requires that all requested parameters be specified before a lease is established,


both the dhcpcOptionSet( ) and dhcpcOptionAdd( ) calls must precede the
synchronous dhcpcBind( ) call that establishes the lease.
The preceding code example illustrates synchronous execution of a DHCPv4
request. For asynchronous execution of a DHCPv4 request, you need to implement
an event hook routine similar to the one that follows for handling lease events.
void myLeaseEventHookRoutine( int leaseEvent, void *pCookie )
{
switch (leaseEvent)
{
case DHCPC_LEASE_NEW :
/* this case gets called when a new lease is established */
printf(" DHCPC_LEASE_NEW \n ");
break;

case DHCPC_LEASE_INVALID : 10
/* this case gets called when the client gives up... */
printf(" DHCPC_LEASE_INVALID \n ");
break;

default:
printf(" leaseEvent = %d \n ", leaseEvent );
break;
}
}

To query the local DHCPv4 client for a parameter value from the lease information
it has retrieved, call dhcpcOptionGet( ). This routine checks whether the lease
associated with a particular lease cookie is valid and whether the server provided
the requested parameter. If so, dhcpcOptionGet( ) copies the parameter value into
a buffer. Otherwise, it returns ERROR. A call to dhcpcOptionGet( ) generates no
network traffic; it queries the local DHCPv4 client for the information it needs.
The following sample demonstrates the use of this routine:
struct in_addr webServer;
STATUS result;
int length = sizeof (struct in_addr);
char ipAddress[INET_ADDR_LEN];

...
result = dhcpcOptionGet (pLeaseCookie, _DHCP_DFLT_WWW_SERVER_TAG,
&length, (char *) &webServer);
if (result == OK)
{
inet_ntoa_b (webServer, ipAddress);
printf("Primary web server: %s\n", ipAddress);
}...

191
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NOTE: To check on parameters associated with a lease established at boot time, use
the pDhcpcBootCookie global variable as the lease cookie for dhcpcOptionGet( ).

In addition to dhcpcOptionGet( ), you can use dhcpcParamsGet( ) to retrieve


multiple lease parameter values simultaneously. The DHCP client library also
provides other routines that you can use to get the values of particular parameters
(such as the lease timers) without supplying their option tags.For more
information on DHCP client features, see the dhcpcLib reference entry.

NOTE: If you already have an IP address and do not want another but want to
query the server for any other information it has for you, call dhcpcInformGet( ).

10.4 Working with the DHCPv4 Relay Agent


Working with a DHCP Relay Agent involves configuring the relay agent to find a
server and configuring the server to accept requests from appropriate agents.

NOTE: In the sections that follow, the examples talk of editing tables defined in
usrNetDhcprCfg.c, usrNetDhcpcCfg.c, and usrNetDhcpsCfg.c. If you are doing
a BSP build, the table definitions are in:
installDir/vxworks-6.n/target/src/config/usrNetwork.c

Configuring the Relay Agent to Find a Server

In addition to setting values for the parameters associated with the DHCP relay
agent, you also need tell the relay agent how to find other DHCP relay agents or
servers with whom to relay DHCP requests. To do this, you must edit the
dhcprTargetTbl[ ] table defined in usrNetDhcprCfg.c. This table is of the form:
DHCP_TARGET_DESC dhcprTargetTbl [] =
{
/*
IP address of DHCP target servers
---------------------------------
*/
/* {"192.0.2.1"}, */
};

192
10 Working with DHCPv4 and DHCPv6
10.4 Working with the DHCPv4 Relay Agent

Each entry in the table must specify a valid IP address for a DHCP server on a
different subnet than the relay agent. The relay agent transmits a copy of all DHCP
messages sent by clients to each of the specified addresses. The agent does not set
the IP routing tables so that the specified target addresses are reachable.
The relay agent forwards DHCP client messages through only a limited number of
targets: the DHCP Server/Relay Agent Network Radius. When the configured
value is exceeded, the message is silently discarded. This value is increased only
when a DHCP agent forwards the message. It is completely independent of the
similar value used by IP routers. RFC 1542 specifies the maximum value of 16 for
this constant. The default hops value is four.
Beyond providing the list of target addresses, and optionally changing the
maximum number of hops permitted, no further action is necessary. The DHCP
relay agent executes automatically whenever it is included in the image.
10

Identifying the Interfaces of Importance to the Relay Agent

Use a dhcprIfTbl to identify which interfaces the relay agent should monitor and
use. For example:
/*
* This table contains a list of interfaces that the relay agent
* will listen to. The boot device is used when the table's
* first entry is the null string.
*/
DHCPR_IF_DESC dhcprIfTbl [] =
{
{""} /* Use primary interface */
/* Sample interface entries. */
/* {"fei1"}, */
/* {"ln0"} */
};

By default, the table is empty and the relay agent notices only the boot interface.
However, to function correctly, the relay agent needs at least two interfaces. Thus,
you must populate this table with the names of the other interfaces that the relay
agent should monitor and use.
The agent does not start or configure the interfaces listed in dhcprIfTbl. The
primary interface (usually the boot device) is automatically configured by the
general network initialization code. Use the INCLUDE_ADDIF component to
configure an additional interface.

193
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Alternatively, interface(s) can be configured manually, as shown by the example


below, prior to the call to dhcprInit( ):
ipAttach (1, "fei");
ifMaskSet ("fei1", 0xffffff00);
ifAddrSet ("fei1", "10.20.30.1");

The target configured as a relay agent must have IP forwarding enabled: set the
IPFORWARDING_CFG parameter to TRUE. By default, this parameter is set to
FALSE.

Configuring a Server to Accept Requests from Your Relay Agent

The Wind River DHCP server accepts relayed messages only from those DHCP
relay agents (identified by IP address and subnet number) that are listed in
dhcpsRelayTbl[ ] defined in usrNetDhcpsCfg.c.
DHCPS_RELAY_DESC dhcpsRelayTbl [] =
{
/*
IP address of agent Subnet Number
-------------------- -------------
*/
/* {"192.0.2.254", "192.0.2.0"}, */
};

This table acts as an authorization list. If messages arrive from relay agents not
listed in the table, the messages are ignored. Consider the example in Figure 10-1.

Figure 10-1 Configuring a Server

Target 1 Target 2 Target 3

DHCP DHCP DHCP


Client Relay Sever

10.20.30.1 motfcc0: 10.20.30.240 fei0: 10.20.40.250


motscc0: 10.20.40.240

194
10 Working with DHCPv4 and DHCPv6
10.5 Working with the DHCPv4 Server

DHCP relay configuration summary:



dhcprTargetTbl contains an entry for the DHCP server:
{"10.20.40.250"},

dhcprIfTbl contains entries for monitored interfaces:
{"motfcc0"},{"motscc0"}
■ IP_FORWARDING_CFG is set to TRUE.
DHCP server configuration summary:
■ dhcpsLeaseTbl would have an entry for client whose MAC address is
0x08:00:3D:21:FE:90:
{"ent1", "10.20.30.1", "10.20.30.1",
"snmk=255.255.255.0:clid=\"1:0x08003D21FE90\""},
10
■ dhcpsRelayTbl would have an entry for DHCP relay agent:
{"10.20.30.240", "10.20.30.0"},
■ dhcpsIfTbl contains an entry for monitored interface:
{"fei0"}
■ dhcpsTargetTbl is left as default since this server is not performing relay
services.
■ Add a route to the relay agent:
-> routec "-v add -host 10.20.30.240 10.20.40.240"

10.5 Working with the DHCPv4 Server


Configuring the Wind River DHCP server involves more than setting parameter
values in INCLUDE_DHCPS and INCLUDE_DHCPS_SHARE. It also requires that
you provide some initial set up information in the DHCP lease table,
dhcpsLeaseTbl[ ]. For information on how to edit this table, see Configuring the
Lease Table in the Wind River DHCP Server, p.196.
Editing this table directly is possible only at build time. To add entries to this table
at run-time, use dhcpsLeaseEntryAdd( ). For information on how to use this
routine, see the dhcpsLeaseEntryAdd( ) reference entry. To preserve these
run-time table edits across a reboot, you will need to implement a storage routine

195
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

and name that routine in the DHCPS_LEASE_HOOK parameter associated with this
configuration component. For information on how to write this routine, see Storing
and Retrieving Active Network Configurations, p.198.
Finally, if your DHCP server needs to support DHCP relay agents, you will need
to identify those agents in dhcpsRelayTbl[ ]. For more information, see
Configuring the Relay Agent Table in the Wind River DHCP Server, p.198.

Configuring a DHCPS Interfaces Table

This table supplies the list of interfaces to which the server will listen. To configure
the server to use the boot device, set up the table’s first entry to be a null string.
DHCPS_IF_DESC dhcpsIfTbl [] =
{
{""} /* Use primary interface */
/* Sample interface entries. */
/* {"fei1"}, */
/* {"ln0"} */
};

Configuring the Lease Table in the Wind River DHCP Server

To determine its initial configuration data, the Wind River DHCP server uses the
dhcpsLeaseTbl[ ] defined in usrNetDhcpsCfg.c. This table describes the server’s
pool of network configuration parameter sets. It has the following format:
DHCPS_LEASE_DESC dhcpsLeaseTbl [] =
{
/* {"Name", "Start IP", "End IP", "parameters"} */

{"dflt", NULL, NULL, DHCPS_DEFAULT_ENTRY},

/* Sample database entries. */

/* {"ent1", "192.0.2.24", "192.0.2.24",


"clid=\"1:0x08003D21FE90\":maxl=90:dfll=60"}, */

/* {"ent2", "192.0.2.25", "192.0.2.26",


"snmk=255.255.255.0:maxl=90:dfll=70:file=/vxWorks"},*/

/* {"ent3", "192.0.2.27", "192.0.2.27",


"maxl=0xffffffff:file=/vxWorks"}, */

/* {"entry4", "192.0.2.28", "192.0.2.29",


"albp=true:file=/vxWorks"} */

};

196
10 Working with DHCPv4 and DHCPv6
10.5 Working with the DHCPv4 Server

Each entry in this lease table must include a unique entry name of up to eight
characters and an IP address range for assignment to requesting clients. The
parameters field contains a colon-separated list of optional parameters for
inclusion in the DHCP server’s response. If subnetting is in effect, a critical entry
in the parameters field is the subnet mask (snmk). The server does not issue
addresses to clients that would change their current subnet. The address pool must
specify a correct subnet mask if the default class-based mask is not valid.
You can find complete description of the parameters field in the reference entries
for the DHCP server. Any parameters not specified take default values according
to the Host Requirements Documents (RFC 1122 and RFC 1123). The server can
also read additional entries from an optional storage hook (Storing and Retrieving
Active Network Configurations, p.198). The most commonly used lease table
parameters are:
clid 10
Indicates that this is a manual lease. Such a lease is issued only to the client
with the matching type:id pair. The address range for these entries must
specify a single IP address. The sample shown for “ent1” uses the
hardware address that the Wind River DHCP client uses for an identifier.
maxl
Indicates that this lease is dynamic. This parameter specifies the maximum
lease duration granted to any requesting client. The automatic lease
illustrated in the third sample entry is implied by the assignment of an
infinite value for maxl.
albp
Indicates a special type of automatic lease. Setting the albp parameter to
true in the fourth entry marks this lease as suitable for BOOTP clients that
contact this DHCP server.
siad
Specifies the (boot) server Internet address, the IP address of the boot host.
Of the parameters shown above, the first three, clid, max1, and albp, indicate lease
types. The server uses the lease type to select one of the three supported
mechanisms for IP address allocation. With manual allocation, DHCP simply
conveys the related manual lease to the client. If dynamic allocation is used, the
protocol assigns one of the dynamic leases to the client for a finite period.
Automatic allocation assigns a permanent IP address from the corresponding
automatic leases.
Dynamic allocation is the only method that allows reuse of addresses. The
allocation type defines the priority for assigning an IP address to a DHCP client.

197
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Manual allocations have the highest priority, and automatic allocations the lowest.
Among automatic leases, the preferred configurations are those available only to
DHCP clients.

Configuring the Relay Agent Table in the Wind River DHCP Server

If the DHCP server expects messages from relay agents, you must list those agents
(identified by IP address and subnet number) in the dhcpsRelayTbl[ ]. This table
acts as an authorization list. If messages arrive from relay agents not listed in the
table, the messages are ignored.
DHCPS_RELAY_DESC dhcpsRelayTbl [] =
{
/*
IP address of agent Subnet Number
-------------------- -------------
*/
/* {"192.0.2.254", "192.0.2.0"}, */
};

Storing and Retrieving Active Network Configurations

To store and retrieve network configuration information, you need to implement


an address storage routine and a lease storage routine. The lease storage routine
uses the prototype:
STATUS dhcpsLeaseStorageHook
(
int op, /* requested storage operation */
char * pBuffer, /* memory location for record of active lease */
int dataLen /* amount of lease record data */
)

! CAUTION: Not providing a storage routine may cause DHCP to fail.

Your lease storage routine must store and retrieve active network configurations.
To install the routine you created, set DHCPS_LEASE_HOOK (a configuration
parameter) to a string containing the routine name. The address storage routine
uses the following prototype:

198
10 Working with DHCPv4 and DHCPv6
10.5 Working with the DHCPv4 Server

STATUS dhcpsAddressStorageHook
(
int op, /* requested storage operation */
char * pName, /* name of address pool entry */
char * pStartIp, /* first IP address in range */
char * pEndIp, /* last IP address in range */
char * pParams /* lease parameters for each address */
)

Your address storage routine (optional) stores and retrieves additional


address-pool entries using dhcpsLeaseEntryAdd( ). To preserve these entries, set
DHCPS_ADDRESS_HOOK (a configuration parameter) to the name of your storage
routine. If you do not do this, any active leases using alternate entries are not
renewed when the server is restarted.
The cmd parameters of both storage routines expect one of the following values:1
DHCPS_STORAGE_START
10
Tells your storage routine to perform any necessary initialization. Your
storage routine should “reset” and thus prepare to return or replace any
previously stored data.
DHCPS_STORAGE_STOP
Tells your storage routine to perform any necessary cleanup. After a stop, the
storage routine should not perform any reads or writes until after the next
start.
DHCPS_STORAGE_WRITE
Tells the routine to store network configurations. Each write must store the
data to some form of permanent storage.
The write functionality of your lease storage routine is critical. It is required to
preserve the integrity of the protocol and prevent assignment of IP addresses
to multiple clients. If the server is unable to store and retrieve the active
network configurations, the results are unpredictable. The write functionality
of the lease storage routine must accept a sequence of bytes of the indicated
length.
The write functionality of the address storage routine must accept
NULL-terminated strings containing the entry name, starting and ending
addresses, and additional parameters.
If a write completes successfully, the routine must return OK.

1. These symbolic constants are defined in dhcpsLib.h.

199
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCPS_STORAGE_READ
Tells your storage routine to retrieve network configurations. Each read must
copy the data (stored by earlier writes) into the buffers provided. The returned
information must be of the same format provided to the write operation.
If a read completes successfully, your routine must return OK. If earlier reads
have retrieved all available data, or no data is available, your routine must
return ERROR. The server calls your routine with read requests until ERROR
is returned.
DHCPS_STORAGE_CLEAR
Used only in calls to your lease storage routine. This value tells your routine
that any data currently stored is no longer needed. Following this operation,
reads should return error until after the next write.

NOTE: If you are configuring address storage and lease storage hooks, remove the
comments from the hook declarations in the server configlette:
installDir/vxworks-6.n/target/config/comps/src/net/coreip/apps/
usrNetDhcpsCfg.c
/* Include these declarations if hooks are defined. */
/* IMPORT STATUS DHCPS_LEASE_HOOK (int, char *, int); */
/* IMPORT STATUS DHCPS_ADDRESS_HOOK (int, char *, int); */

10.6 Using DHCPv6


The Wind River DHCPv6 implementation provides DHCP services using IPv6
instead of IPv4. The DHCPv6 implementation includes a client, a server, and a
relay agent. Also included are DHCPv6 show routines.
The importance of DHCPv6 at boot time may be somewhat reduced under IPv6.
This is a consequence of the IPv6 RFC 2462 autoconfiguration functionality. The
autoconfiguration process lets a node create a link-local IPv6 address and verify its
uniqueness on a link using the Duplicate Address Detection procedure. Using this
address, a node has immediate IP-mediated access to its IPv6 peers on the local
link. The target may then continue the autoconfiguration process to create a global
address from information supplied by routers on the local link, or it may use
DHCPv6 to negotiate a global address. A global address is required for
communication with nodes off the local link.

200
10 Working with DHCPv4 and DHCPv6
10.6 Using DHCPv6

10.6.1 Wind River Implementation

The DHCPv6 client provides dh6cInfoGet( ), which enables an IPv6 node to


retrieve configuration information provided by the DHCPv6 server. The DHCPv6
client does not apply the retrieved configuration information to interfaces. For the
list of supported options, see the reference entries for dhcp6c and dhcp6s. The
Wind River DHCPv6 client is not a complete implementation. In particular:
The current release of Wind River DHCPv6 does not support temporary addresses;
only non-temporary addresses (see RFC 3315) are supported.

NOTE: The Wind River DHCPv6 implementation supports prefix delegation, but
it does not implement the full standard.

10
10.6.2 Configuring VxWorks for DHCPv6

As described in 10.6.1 Wind River Implementation, p.201, the Wind River


Network Stack supports the following DHCPv6 configuration components:

DHCPv6 Run-time Client

DHCPv6 Server

DHCPv6 Relay Agent

DHCPv6 Client Show Routines
These components are all listed under the
Network Components > Network Applications > DHCPv6 Components folder
in Workbench.

DHCPv6 Run-time Client

The INCLUDE_DHCP6C component pulsl in the DHCPv6 run-time client, which is


implemented in dhcp6c and dhcp6c_ia. For more information, see the dhcp6c
reference entries. This component requires the following configuration
components:

INCLUDE_IPV6

INCLUDE_UDPV6
The INCLUDE_DHCP6C component contains the following configuration
parameters:

201
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCP6C_UPORT

Synopsis: UDP Port monitored by DHCPv6 Servers.


Default: 547

DHCP6C_DPORT

Synopsis: UDP Port monitored by DHCP6 Clients.


Default: 546

DHCP6C_OPTION

Synopsis: Options for DHCPv6 Client.


Default: DHCP6C_OPT_SEND_IA_ID

DHCP6C_VERBOSE

Synopsis: DHCPv6 client verbosity level, 0-2.


Default: 0

DHCP6C_UPLINK_IF

Synopsis: DHCPv6 client interface connected to the upper link.


Default: "motfcc0"

DHCP6C_DOWNLINK_IF

Synopsis: DHCPv6 client interface connected to down stream link.


Default: "motscc0"

DHCP6C_PRIORITY

Synopsis: DHCPv6 Client Task Priority.


Default: 80

DHCP6C_SIZE

Synopsis: DHCPv6 Client Task Stack Size, in bytes.


Default: 10000

DHCP6C_KEY_REALM_STRING

Synopsis: DHCPv6 administrative domain name.


Default: "dhcpv6Admin"

202
10 Working with DHCPv4 and DHCPv6
10.6 Using DHCPv6

DHCP6C_KEY_SECRET_STRING

Synopsis: Secret key shared between DHCPv6 client and server.


Default: "5pvW2g48OHPvkYMJSw0vZA=="

DHCP6C_KEY_EXPIRE_STRING

Synopsis: Key expiration in seconds ("forever","0" = never expires).


Default: "forever"

DHCPv6 Server

The INCLUDE_DHCP6S component pulls in the DHCPv6 server, which is


implemented in dhcp6s. This component requires the following configuration
components: 10

■ INCLUDE_IPV6
■ INCLUDE_DISK_UTIL
■ INCLUDE_DOSFS_MAIN
■ INCLUDE_DOSFS_FMT
■ INCLUDE_XBD_RAMDRV
The INCLUDE_DHCP6S component contains the following configuration
parameters:

DHCP6S_UPORT

Synopsis: UDP Port monitored by DHCPv6 Servers


Default: 547

DHCP6S_DPORT

Synopsis: UDP Port monitored by DHCP6 Clients


Default: 546

DHCP6S_CONF_FILE_NAME

Synopsis: DHCPv6 server configuration file name


Default: "dhcp6s.conf"

203
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCP6S_RAMDISK_SIZE

Synopsis: DHCPv6 Server Ram Disk Size, in bytes. Must be an even multiple
of 512.
Default: 512*32

DHCP6S_VERBOSE

Synopsis: DHCPv6 server verbosity level, 0-2.


Default: 0

DHCP6S_DOWNLINK_IF

Synopsis: DHCPv6 server interface connected to down stream link.


Default: "motfcc0"

DHCP6S_PRIORITY

Synopsis: DHCPv6 Server Task Priority


Default: 80

DHCP6S_SIZE

Synopsis: DHCPv6 Server Task Stack Size, in bytes.


Default: 10000

DHCPv6 Relay Agent

The INCLUDE_DHCP6R component pulls in the DHCPv6 Relay Agent, which is


implemented in dhcp6relay. For more information, see the dhcp6relay reference
entries. This component requires the following configuration components:
■ INCLUDE_IPV6

INCLUDE_DISK_UTIL
The INCLUDE_DHCP6R component contains the following configuration
parameters:

DHCP6R_HOP_LIMIT

Synopsis: DHCPv6 relay hop limit


Default: 32

204
10 Working with DHCPv4 and DHCPv6
10.6 Using DHCPv6

DHCP6R_UPORT

Synopsis: UDP Port monitored by DHCPv6 Servers


Default: 547

DHCP6R_DPORT

Synopsis: UDP Port monitored by DHCPv6 Clients


Default: 546

DHCP6R_SRC_ADDR

Synopsis: Optional Source Address for DHCPv6 Relay Agent


Default: NULL

DHCP6R_SERVER_ADDR 10

Synopsis: Optional Server Address for DHCPv6 Relay Agent


Default: NULL

DHCP6R_VERBOSE

Synopsis: DHCPv6 Relay Agent verbosity level, 0-2.


Default: 0

DHCP6R_UPLINK_IF

Synopsis: Optional upper link interface for DHCPv6 Relay Agent.


Default: "motfcc0"

DHCP6R_DOWNLINK_IF

Synopsis: DHCPv6 Relay Agent interface connected to down stream link.


Default: "motscc0"

DHCP6R_PRIORITY

Synopsis: DHCPv6 Relay Agent Task Priority


Default: 80

DHCP6R_SIZE

Synopsis: DHCPv6 Relay Agent Task Stack Size, in bytes.


Default: 10000

205
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

DHCPv6 Client Show Routines

The INCLUDE_DHCP6C_SHOW component pulls in dhcp6cShow, a library that


supplies show functionality for the DHCPv6 client. For more information, see the
dhcp6cShow reference entries.

206
11
Creating Network Applications
as RTPs

11.1 Introduction 207


11.2 Network Applications Supported in RTPs 208
11.3 Working with Application RTPs 216
11.4 Using Socket Connections with RTPs 223

11.1 Introduction
The core network stack functionality runs in the kernel only. This core network
stack functionality consists of implementations of fundamental networking
protocols such as IP, TCP, UDP as well as the network interface drivers and the
MUX functionality. Most network applications can run either in the kernel or as an
RTP, provided all services upon which they rely are also supported in RTPs.

NOTE: In the process of porting network applications to RTPs, Wind River has
exposed both the standard socket APIs and the routing socket APIs at the RTP
level. If you have an application that limits (or can limit) its interaction with the
network stack to standard or routing socket API calls, that application is a good
candidate for porting to run in an RTP.

For a listing of which applications have been ported to run as an RTP, see
Table 11-1. In this table, if the IP version is relevant to the application but the listing
does not specify either IPv4 or IPv6, assume it is the original IPv4-only application.

207
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Applications that are independent of the underlying IP version (those are DNS and
TFTP) are supported over both IPv4 and IPv6, although no special mention of this
is made in the table.

Table 11-1 Network Services and RTP Compatibility

Kernel Only Kernel or Single RTP a Kernel and Multiple RTPs

BOOTP FTP (server, v4/v6) DNS resolver library

DHCP RIP DNS (client)

DHCP v6 TFTP (server) FTP (client), FTP6 (client)

NFS ping

RIPng ping6

rlogin (server) rlogin (client)

SNTP Telnet (client v4/v6)

Telnet (server, v4/v6) TFTP (client)


a. For the FTP server, RIP, and the TFTP server, a target supports only a single instance.
You can run this single instance either in the kernel or in an RTP.

For an application that you have written to use network services, no changes are
required to run that application in the kernel. To run that application as an RTP,
you will need to make a few changes. This chapter provides information on how
to modify an existing network application to run as an RTP. Also included is
information on how RTPs can use sockets.

11.2 Network Applications Supported in RTPs


Many network applications use a client/server model. The server side of the
application is typically implemented as a daemon that runs in the context of its
own independent task. The client side of the application is typically implemented
as a library whose routines execute in the context of the caller. All network
applications, both the client and the server side, are supported for use in the kernel.

208
11 Creating Network Applications as RTPs
11.2 Network Applications Supported in RTPs

NOTE: The clients provided are intended as sample .vxe files. They are not
intended to be feature-complete production applications. However, the servers
(FTP, TFTP and RIP) are production applications as are ping and ping6. All others
are samples to use as starting points for your own implementations.

11.2.1 DNS Resolver in an RTP

Using the DNS resolver within an RTP requires no special changes. Within your
application, call resolvInit( ) when you initialize the RTP, then proceed to use the
resolvLib library.

11.2.2 FTP Server in an RTP


11
The RTP implementation of the FTPv6 server, which handles both IPv4 and IPv6,
is supplied in:
instalDir/vxworks-6.n/target/usr/apps/coreip/ftpd/ftp6dMain.c
This directory also contains a makefile that you can use to build the ftp6d.vxe ELF
file. To load this RTP, call rtpSp( ). From a kernel shell, cd to the directory
containing the ftp6d.vxe and try the following:
-> rtpSp "ftp6d.vxe"

By default ftp6d.vxe acts as a dual-server. Specifying an argument of -4 will give


you an IPv4-only server and specifying an argument of -6 will give you an
IPv6-only server. In addition, because the server is implemented as a daemon, this
RTP does not shut itself down. You must shut it down explicitly.

NOTE: To run the FTP server in an RTP, the kernel must include support for POSIX
timers. Use the INCLUDE_POSIX_TIMERS component to include POSIX timer
support in an image.

11.2.3 FTP Client in an RTP

Running either the IPv4 or IPv6 FTP client as an RTP requires no special changes.
Within your application, call ftpLibInit( ) or ftp6LibInit( ) when you initialize the
RTP, then proceed to use the library.

209
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

11.2.4 Ping or Ping6 in an RTP

The RTP implementation of ping is supplied in:


instalDir/vxworks-6.n/target/usr/apps/coreip/pingv4/pingMain.c
The RTP implementation of ping6 is supplied in:
instalDir/vxworks-6.n/target/usr/apps/coreip/pingv6/ping6Main.c
These directories also contain Makefiles that you can use to build the ping.vxe or
ping6.vxe ELF file.
To load the ping.vxe RTP, call rtpSp( ). From a kernel shell, cd to the directory
containing the ping.vxe and try the following:
-> rtpSp "path/ping.vxe remote_system number_of_packets options"

Internally, ping.vxe initializes the ping library, handles the ping request for the
requested number of packets, and then exits. Exiting shuts down the RTP. If you
specify a continuous ping, a ping with a number_of_packets value of 0, the ping
runs forever, or until you shut it down explicitly. The ping6.vxe RTP works much
the same way, but runs a different library.

11.2.5 Remote Command Library (remLib) in an RTP

Using the remLib functionality within an RTP requires no special changes. Within
your RTP, call remLibInit( ) when you initialize the RTP, then proceed to use the
resolvLib library routines such as rcmd( ) and rresvport( ).

11.2.6 RIP in an RTP

The RTP implementation of RIP is supplied in:


instalDir/vxworks-6.n/target/usr/apps/coreip/ripv4/ripMain.c
This directory also contains a makefile for building the rip.vxe ELF file.

Starting the RIP RTP

To load the RIP RTP, call rtpSp( ). From a kernel shell, cd to the directory
containing the rip.vxe and run the command according to the following syntax:
-> rtpSp "path/rip.vxe parameter1 parameter2 parameter3 ... parameter9"

210
11 Creating Network Applications as RTPs
11.2 Network Applications Supported in RTPs

The rip.vxe RTP takes 9 parameters:


parameter1—supplier or listener
The value of this parameter determines whether RIP advertises routes or
routines as a passive listener. A zero value, the default, configures RIP as a
passive listener. Any non-zero value configures the RIP server to send out
routing information and updates no matter how many physical interfaces are
attached to it.
parameter2—gateway or not
The value of this parameter identifies whether this server is a router to the
greater Internet. Any non-zero value tells the server that it is a router to the
greater Internet. If this is not the case, specify a zero value (the default).

! WARNING: Do not set RIP_GATEWAY to 1 unless this really is the general gateway.
Setting this to 1 configures the RIP server to send out a default route (0.0.0.0) with
every routing update. This tells all the other listening servers that this server is the
11
default route for its subnet. This causes all packets to go to this router if they do not
have a route that matches an existing entry in their routing table.

parameter3—multicast or broadcast updates


The value of this parameter determines whether RIP should multicast updates
or broadcast route updates. Any non-zero value tells the server to multicast
route updates to address 224.0.0.9 instead of broadcasting to the subnet. A
non-zero value for this parameter is valid only if the version, parameter4, is set
to 2, otherwise ERROR is returned. A value of zero (default) specifies that
route updates should be broadcast.
parameter4—version
The value of this parameter supplies the version number of the RIP protocol.
The version determines the format used for outgoing RIP messages, and also
sets the initial settings of the MIB-II compatibility switches in combination
with the multicast flag, parameter3. A version of 1 (the default) restricts all
incoming traffic to the older message type (RFC 1058) and broadcasts RIPv1
updates. A version of 2, with multicast set to 0, sets the receive switch to accept
either type and broadcast RIPv1 compatible updates. A version of 2 with
multicast, parameter3, set to non-zero sets the receive switch to accept only
RIPv2 messages and multicasts RIPv2 updates. SNMP agents can alter those
settings on a per-interface basis after the startup is complete.
parameter5—timer rate
The value of this parameter supplies the resolution value (in seconds) for the
RIP timers. The default value is 1.

211
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

parameter6—supply interval
The value of this parameter supplies the length of the interval, in seconds,
between successive route updates. The default value is 30.
parameter7—expire interval
The value of this parameter supplies the length of the interval, in seconds, after
which a stale route (a route that has not been refreshed by a neighbor's update)
is marked unreachable and deleted from the system routing table. Expired
routes are retained in RIP's routing table until the garbage timeout, parameter8,
so that their expiration can be announced in subsequent route updates. The
default value is 180 seconds.
parameter8—garbage interval
The value of this parameter supplies the length of the interval, in seconds, after
which a stale route is removed from RIP's routing table and not advertised
anymore.
parameter9—authentication type
The value of this parameter specifies the default authentication type. The valid
values for this parameter are as follows:
1 to specify M2_rip2IfConfAuthType_noAuthentication
2 to specify M2_rip2IfConfAuthType_simplePassword
3 to specify M2_rip2IfConfAuthType_md5
The rip.vxe application exits with a value of 1 on error and with value of 0 (zero)
on user termination. Sample usages:
> rtpSp "rip.vxe 1 0 0 1 1 30 180 300 1"
> rtpSp "rip.vxe 1 0 0 2"
> rtpSp "rip.vxe"

Shutting Down the RIP RTP

To shut down the RIP RTP in a controlled manner, use rtpKill( ) as follows:
-> rtpKill rtpId, 15

In the command above, substitute rtpId with the RTP ID of the RIP application.
This command ensures a proper shutdown of the application, which is preferred
to the abort that would be effected by a rtpDelete( ) call or an rtpKill(rtpId, 9) call.

212
11 Creating Network Applications as RTPs
11.2 Network Applications Supported in RTPs

Managing the RIP RTP

For an application running in the kernel, you can manage that application by
invoking its management routines from the kernel shell or from another program
running in the kernel. An application in an RTP runs in its own private virtual
memory space. Consequently, the management routines for that application are
inaccessible from outside the RTP. For applications that allow run-time
configuration changes, applications such as RIP, this can be very limiting.
To overcome this limit, the RIP implementation ported to run in a VxWorks RTP
now supports a set of management routines that are callable from outside the RTP.
Internally, these management routines use a simple RPC-like mechanism to
communicate with the application running in the RTP.
To access the RIP management functions from outside the RTP, compile and link in
the ripCmdFuncs.c file supplied in:
installDir/vxworks-6.n/target/usr/apps/coreip/ripv4/ripCmdFuncs.c 11

This file depends upon ripAppDefs.h. Thus, when you copy ripCmdFuncs.c into
your project, you also need to copy in:
installDir/vxworks-6.n/target/usr/apps/coreip/ripv4/ripAppDefs.h
If working with a BSP build, make sure that you update you BSP’s Makefile to
build ripCmdFuncs.c.
The API supplied by ripCmdFuncs requires SNS support, as well as the SAL client
and the SAL server. To include these components in a build, make sure that you
include:
■ INCLUDE_SNS
■ INCLUDE_SAL_CLIENT

INCLUDE_SAL_SERVER
■ INCLUDE_UN_COMP
■ INCLUDE_UN
For details, see 11.4.1 Configuring VxWorks for the SAL Library, p.225.
To include these components in a BSP build, your BSP’s config.h must define the
following:
#define INCLUDE_SNS
#define INCLUDE_SAL_CLIENT
#define INCLUDE_SAL_SERVER
#define INCLUDE_UN_COMP
#define INCLUDE_UN

213
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The RIP management routines supplied by ripCmdFuncs.c are as follows:


_ripRouteShow( ) - call ripRouteShow( ) in an RTP
_ripIfShow( ) - call ripIfShow( ) in an RTP
_ripLeakHookDelete( ) - call ripLeakHookDelete( ) in an RTP
_ripSendHookDelete( ) - call ripSendHookDelete( ) in an RTP
_ripRouteHookDelete( ) - call ripRouteHookDelete( ) in an RTP
_ripIfSearch( ) - call ripIfSearch( ) in an RTP
_ripIfReset( ) - call ripIfReset( ) in an RTP
_ripFilterEnable( ) - call ripFilterEnable( ) in an RTP
_ripFilterDisable( ) - call ripFilterDisable( ) in an RTP
_ripDebugLevelSet( ) - call ripDebugLevelSet( ) in an RTP
_ripAuthHookDelete( ) - call ripAuthHookDelete( ) in an RTP
_ripAuthKeyShow( ) - call ripAuthKeyShow( ) in an RTP
_ripAuthKeyAdd( ) - call ripAuthKeyAdd( ) in an RTP
_ripAuthKeyDelete( ) - call ripAuthKeyDelete( ) in an RTP
_ripIfExcludeListAdd( ) - call ripIfExcludeListAdd( ) in an RTP
_ripIfExcludeListDelete( ) - call ripIfExcludeListDelete( ) in an RTP
_ripIfExcludeListShow( ) - call ripIfExcludeListShow( ) in an RTP
_ripIfAddrReset( ) - call ripIfAddrReset( ) in an RTP
_ripIfAddrExcludeListAdd( ) - call ripIfAddrExcludeListAdd( ) in an RTP
_ripIfAddrExcludeListDelete( ) - call ripIfAddrExcludeListDelete( ) in an RTP
These routines are similar to their kernel-resident equivalents, but with the
following differences:
■ Each routine has a “_” prefixed to its routine name.
■ Each routine takes the RTP ID as its first parameter.
For example, to invoke ripRouteShow( ) in the RIP RTP, you would call:
_ripRouteShow(0x12345);

In this call, 0x12345 is the RTP ID for the RTP running the RIP application. This
RTP ID is returned as the value of the call that launched the RTP. Similarly, to call
ripIfAddrReset( ) for the RIP application running in an RTP with an ID of 0x12345,
you would call:
_ripIfAddrReset (0x12345, char * pIfName, char * pIfAddr, u_long mask1)

214
11 Creating Network Applications as RTPs
11.2 Network Applications Supported in RTPs

11.2.7 Rlogin Client in an RTP

Using the rlogin client functionality within an RTP requires no special changes.
Within your RTP, call rlogInit( ) when you initialize the RTP, then proceed to use
the rlogLib library routines such as rlogin( ). The rlogin client is compatible with
both IPv4 and IPv6.

11.2.8 Telnet Client in an RTP

Using the Telnet client functionality within an RTP requires no special changes.
Within your RTP, call telnetcInit( ) when you initialize the RTP, then proceed to use
the telnetcLib library routines such as telnet( ).

11.2.9 TFTP Client in an RTP 11

Using the TFTP client functionality within an RTP requires no special changes.
Within your RTP, call tftpInit( ) when you initialize the RTP, then proceed to use
the tftpLib library routines within the RTP.

11.2.10 TFTP Server in an RTP

The RTP implementation of the TFTP Server (the Trivial File Transfer Protocol
daemon), tftpd.vxe, is supplied in:
instalDir/vxworks-6.n/target/usr/apps/coreip/tftpd/tftpdMain.c
This directory also contains a makefile that you can use to build the tftpd.vxe ELF
file. To load this RTP, call rtpSp( ). From a kernel shell, cd to the directory
containing the tftpd.vxe and try the following:
-> rtpSp "tftpd.vxe"

Because this server is implemented as a daemon, this server does not shut itself
down. You must shut it down explicitly.

11.2.11 General Network/RTP Incompatibilities

As mentioned in the introduction, core network stack protocols such as IP, TCP,
UDP, and the like run in the kernel only, although they are accessible to RTPs
through socket connections and sysctl( ) calls.

215
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Likewise, the MUX functionality and network interface drivers run in the kernel
space only. Thus, if you want to launch and configure a network interface, you do
so within the kernel space. RTPs cannot create and configure network interfaces.
In addition, most network show and configuration utilities are available in the
kernel space only. The exception is the sysctl( ) routine, which is supported as
system call for RTPs.
In addition, because of the isolation of an RTP memory space, RTPs cannot supply
call back routines to kernel-resident network protocols and services. A pointer to
a routine in an RTP memory space would be meaningless at best in the kernel
memory space.

11.3 Working with Application RTPs


VxWorks has historically supported a kernel execution mode only. Both user
applications and central support functionality, such as that provided by the
network stack, all ran in the same memory space. With Base 6, VxWorks now
supports a Real Time Process (RTP) mode in addition to kernel mode. This RTP
mode is based on RTP Executable and Linking Format (ELF) object files. These
object files are fully linked relocatable executables with full name space isolation.
Using an RTP ELF object, you can now isolate an application from the kernel and
from applications running in other RTPs. This isolation of an application to an RTP
ELF object allows for memory protection. There is nothing that compels you to run
an application as an RTP. You can still run it in the kernel. You are also free to run
some applications in the kernel while others execute as RTPs.
All applications, whether running in the kernel or as RTPs can communicate with
each other using AF_LOCAL sockets. In addition, RTP-based applications can
access kernel-resident services using sysctl( ) or system calls. If you add a new
kernel-resident service, you can extend the set of system calls to include that
service.
The following is an overview of working with RTPs. Included are brief discussions
of writing, building, and launching an RTP. More information is available in the
VxWorks Programmer’s Guide.

216
11 Creating Network Applications as RTPs
11.3 Working with Application RTPs

11.3.1 Building an RTP ELF Object File for a Network Application

This section describes how to write and build the venerable “Hello World”
application to run as an RTP. Although “Hello World” is not particularly
representative of a network application, porting “Hello World” to an RTP
demonstrates the most basic mechanics of creating an RTP. To present a more
network-oriented example, this section also presents the RTP port of the FTP
server.

Writing the Code for a “Hello World” RTP

Consider the “Hello World” C program:


#include

int main
( 11
int argc, /* number of arguments */
char * argv[], /* array of arguments */
)
{
printf("hello world\n");
return 0;
}

To create an RTP that uses this main( ), you need to change it slightly to accept all
the inputs provided when an RTP executes its main( ).
#include

int main
(
int argc, /* number of arguments */
char * argv[], /* array of arguments */
char * envp[], /* array of environment strings */
void * auxp /* implementation specific auxiliary vector */
)
{
printf("hello world\n");
return 0;
}

The argc and argv parameters serve their traditional function of passing in a count
of caller arguments as well as an array containing the arguments themselves. You
can use envp and auxp parameters to pass in whatever additional information your
RTP needs at run-time to configure its environment or any auxiliary
implementation-specific need.

217
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Building the Code for a “Hello World” RTP

To build this as an RTP ELF object file, you need a makefile with the following basic
format:
# Makefile - makefile for hello world example RTP
#
# DESCRIPTION
# This file contains the makefile rules for building an example RTP

EXE = helloworld.vxe
OBJS = mainHello.o
include $(WIND_USR)/make/rules.rtp

This makefile assumes that the “Hello World” main( ) is defined in a file called
helloworld.c. To build the helloworld.vxe, you could run the following make:
$ make CPU=cpuType TOOL=toolType

Where:
cpuType is a valid CPU type, such as PPC32.
toolType is a value such as diab or gnu

Setting up Pre-Entry-Point Initialization Routines

What if “Hello World” did not print the message but used a customized service to
transmit the message over the Internet? Such services typically require some
initialization that needs to be completed before an application can use the service.
For some libraries, it is possible to mark the initialization routine with the
_WRS_CONSTRUCTOR attribute. For more information, see 11.3.3 Identifying the
RTP Initialization Routine in a Library, p.222.

Not All Initialization Routines Are Suitable for Pre-Entry-Point Initialization

For some utilities and services, the initialization routines require the run-time
input of information, such as the IP address of a server. These initialization
routines are not suitable for use with the _WRS_CONSTRUCTOR. For libraries and
utilities that depend on this sort of initialization routine, your RTP main( ) needs
to call the initialization routine directly.

218
11 Creating Network Applications as RTPs
11.3 Working with Application RTPs

Writing the Code for an FTP RTP

As an example of a network application ported to run as an RTP, consider the


following code taken from the VxWorks FTP server RTP implementation:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <taskLib.h>
#include <loginLib.h>
#include <applUtilLib.h>
#include <ftpd6Lib.h>

/* forward declarations */
extern int sysClkRateGet (void);

int main
(
int argc, /* number of arguments */
char * argv[], /* array of arguments */
char * envp[], /* array of environment strings */ 11
void * auxp /* implementation specific auxiliary vector */
)
{
STATUS rc = OK;
char * pOptStr;

/* Make stdout unbuffered */


setbuf (stdout, NULL);

if (argc == 1)
pOptStr = "";
else
pOptStr = argv[1];

if (strcmp (pOptStr, "-h") == 0 || strcmp (pOptStr, "-help") == 0)


{
printf ("Allowed argument: -4: for IPv4-only; -6: for IPv6-only;"
"default: dual server. \n");
return 0;
}

printf("\nStarting FTPv4/v6 Server in RTP with \"%s\" ...\n", pOptStr);

/* Start FTP server */


if (ftpd6Init(pOptStr, (FUNCPTR)loginUserVerify, 0) == ERROR)
{
log_err (FTPD_LOG, "Error starting FTPv4/v6 server");
return ERROR;
}

219
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* Enable anonymous login */


if (ftpd6GuestAllow("/anon", "/anon", 0) == ERROR)
{
log_err (FTPD_LOG, "Error while enabling anonymous login");
return ERROR;
}

/* exit the inital task but not the RTP */


taskExit(0);
}

The core of this code is the call to ftpd6Init( ). This call launches a task that serves
as the foundation of the FTP server daemon. Note the taskExit( ) call that comes
before the end brace of the main( ) routine. If execution had reached the end brace,
the RTP and all its tasks, including the FTP server daemon, would have shut down
entirely. More information on why a taskExit( ) is called here is provided in
11.3.4 Shutting down an RTP Application, p.223.

Building the Code for the FTP RTP

To build this as an RTP ELF object file, VxWorks supplies a makefile with the
following content:
# Makefile - makefile for FTP server application
#
# DESCRIPTION
# This file contains the makefile rules to build FTP server
# application executable

EXE = ftpd.vxe
OBJS = ftp6dMain.o
include $(WIND_USR)/make/rules.rtp

This makefile assumes that the main( ) is defined in a file called ftp6dMain.c. To
build the ftpd.vxe, you could run the following make:
$ make CPU=cpuType TOOL=toolType

Where:
cpuType is one of the following:
PPC32
toolType is one of the following:
diab, gnu

220
11 Creating Network Applications as RTPs
11.3 Working with Application RTPs

11.3.2 Launching an RTP

There are several ways to launch an RTP. From a kernel shell, you can use rtpSp( ):
-> rtpSp "ELF_object_file [arg1 [...arg20 ]"

For example:
-> rtpSp "path/ping.vxe remote_system number_of_packets options"

NOTE: The rtpSp( ) utility is supported in the kernel shell only, not the host shell.

If you are using the new command interpreter, you can omit the explicit call to
rtpSp( ). For example:
# path/ping.vxe remote_system number_of_packets options

Alternatively, you can use rtpSpawn( ), which is called internally by rtpSp( ). A


design goal of rtpSpawn( ) is to give you fine-grain control of RTP creation. Thus,
it lets you specify the main( ) task priority, its stack size, and supplemental data 11
that the RTP can use to configure its environment and the application it runs.
Within an rtpSp( ) call, the task priority is set to 220, and the stack size set to 40K
bytes. If these values are not appropriate for your RTP, you can call rtpSpawn( )
directly. In addition, rtpSpawn( ) is supported as a system call and thus is callable
outside the kernel.

What rtpSpawn( ) Does for You

Because rtpSpawn( ) is implemented in the kernel and supported as a system call,


you can call it from code running either in the kernel or in a previously launched
RTP. Internally to rtpSpawn( ), the RTP object file is first validated and then
loaded. The RTP then executes all the initialization routines for referenced
libraries. Within these libraries, the _WRS_CONSTRUCTOR attribute indicates the
RTP initialization routine for the library.
If all goes well with validation, loading, and initialization, rtpSpawn( ) launches
an autonomous task for the RTP. The task routine for this task is the main( )
provided by the RTP ELF object file named in the rtpFileName parameter. Barring
an external shutdown, the life span of an RTP continues until a task within the RTP
calls exit( )—either explicitly or implicitly by letting execution reach the end brace
of the RTP’s main( ). Within the RTP main( ), you can use the standard
taskSpawn( ) and taskCreate( ) routines to launch any additional tasks your
application requires. These tasks run in the context of the RTP and cannot survive
the expiration of the RTP. In addition, the tasks should use taskExit( ) to shut
themselves down. This routine ends the calling task only. Calling exit( ) from any
task within the RTP shuts down the RTP and all its tasks entirely.

221
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

11.3.3 Identifying the RTP Initialization Routine in a Library

When an RTP first launches, and after validation, it runs the initialization routines
for the libraries referenced either directly or indirectly in its main( ). This list of
initialization routines was generated automatically when the RTP was built. When
the build processes the referenced libraries, it notes routines marked with the
_WRS_CONSTRUCTOR attribute. These routines are automatically added to the
RTP’s initialization routine list. When you launch the RTP, the system
automatically calls each of these initialization routines in an order determined by
the priority assigned in the _WRS_CONSTRUCTOR attribute.
After the successful completion of the initialization routines, the RTP executes the
RTP’s main( ).

NOTE: The _WRS_CONSTRUCTOR attribute is not appropriate for initialization


routines that require run-time input. You must call such initialization routines
from the RTP main( ) or a child task launched from the RTP’s main( ).

If you have written a library whose initialization routine you want to mark using
the _WRS_CONSTRUCTOR attribute, the syntax is as follows:
_WRS_CONSTRUCTOR ( functionName, priority )

functionName
This parameter expects the name of the initialization routine.
priority
This parameter expects a value that is used to determine the execution
order of the initialization routines for an RTP. The lower the priority value,
the sooner the routine executes. For example, an initialization routine with
a priority of 10 executes before an initialization routine with a priority of
20. If two initialization routines have the same priority, the execution order
of those same-priority routines is not determinable. Thus, if one routine
must execute before the other, you must adjust the priority values
appropriately.
For an example of how one would use _WRS_CONSTRUCTOR, consider the
hypothetical routine, myLibInit( ):
STATUS myLibInit (void)
{
...
}

222
11 Creating Network Applications as RTPs
11.4 Using Socket Connections with RTPs

To use the _WRS_CONSTRUCTOR attribute to assign a priority of 5, you would


rewrite the routine definition as follows:
_WRS_CONSTRUCTOR (myLibInit,5)
{
...
}

This mechanism is supported by both the Wind River Compiler and the GNU
compiler.

11.3.4 Shutting down an RTP Application

An RTP shuts down entirely when any task in the RTP calls exit( ). Thus, to avoid
accidentally shutting down an RTP, you need to be very careful about when you
call exit( ). You also need to avoid implicit calls to exit( ). These occur if the
execution reaches the end brace of the main( ) routine.
11
One way to avoid an implicit exit( ) call is to call taskExit( ) before execution
reaches the routine end brace. As an alternative to taskExit( ), you could use a
forever loop or you could call:
taskSuspend(0);

In most situations, a taskExit( ) call is a more elegant solution.


To abort an RTP from the outside, call rtpDelete( ). As input, this routine requires
an RTP_ID that identifies the RTP that you want to delete. You received this RTP_ID
as the returned value of the rtpSpawn( ) call that launched the RTP. You can also
get this ID by calling rtpShow( ), which includes RTP IDs in its report.
As an alternative to rtpDelete( ), you can use rtpKill( ) to send a SIGKILL (9) or a
SIGTERM (15) signal to the RTP. If the application installed a signal handler for
SIGTERM, SIGTERM is preferable. A SIGTERM lets the application shut itself
down in a controlled manner. If the application has not installed a signal handler
for SIGTERM, both SIGKILL and SIGTERM abort the application.

11.4 Using Socket Connections with RTPs


For many network applications, BSD sockets in the Internet domain provide the
fundamental communication mechanism. The primary implementation of the

223
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

protocols and services that support Internet sockets resides in the kernel. If your
application runs in the kernel, it can access these socket support services directly.
To make these services available to applications running as RTPs, the kernel
exports a selected set of routines as system calls. This set of socket-related system
calls supports all the well-known routines in the standard BSD socket API plus the
VxWorks-specific connectWithTimeout( ). See Table 11-2.
For more information on using sockets under VxWorks, see 12. Working with
Internet and Local Domain Sockets.

Table 11-2 Socket Calls

Routine Name Use Description

socket( ) Create end point for communication.

bind( ) Associate local address with socket.

listen( ) Mark a socket as accepting connections.

accept( ) Accept a connection on a socket.

connect( ) Initiate a connection on a socket.

sendto( ) Send message from a socket.

sendmsg( ) Send message from socket using structure.

send( ) Send message from connected socket.

recvfrom( ) Receive message from socket and capture addr of sender.

recv( ) Receive message from socket.

recvmsg( ) Receive message from socket and store in structure.

setsockopt( ) Set socket options.

getsockopt( ) Get socket options.

getsockname( ) Get socket name.

getpeername( ) Get name of peer connected to socket.

shutdown( ) Shutdown full-duplex connection on socket.

224
11 Creating Network Applications as RTPs
11.4 Using Socket Connections with RTPs

Using Sockets for Inter-Task Communication

In addition to Internet domain sockets, VxWorks now supports local domain,


AF_LOCAL, sockets for communication among tasks, even tasks that execute in
different memory spaces (the kernel memory space and all the various RTP
memory spaces). Sockets in the AF_LOCAL domain bind to names of files in a local
file system. Under VxWorks, AF_LOCAL sockets support only one set of
communications characteristics: bidirectional, reliable, sequenced,
non-duplicated, and packet-based. This socket communications style type is known
as SOCK_SEQPACKET.

NOTE: The VxWorks implementation of AF_LOCAL sockets supports a


SOCK_SEQPACKET style of communication only.

For more information on AF_LOCAL sockets, see 12. Working with Internet and
Local Domain Sockets.
11

11.4.1 Configuring VxWorks for the SAL Library

The following components support the Socket Application Library and the Socket
Name Service:
■ Socket Application Library Client
■ Socket Application Library Server

Socket Name Service Server in Kernel

Socket Name Service Server in RTP

Socket Name Service Show Routine
These components are all listed under the
Network Components > Distributed Systems Infrastructure >
Socket Applications Library Components folder and under the
Socket Name Service Server subfolder in Workbench.

NOTE: The SAL client and server are not network stack applications. Using them
does not require that you include a network stack in your image.

225
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Socket Application Library Client

The INCLUDE_SAL_CLIENT component pulls in modules that implement the


socket application library client. This component has no configuration parameters
and requires the INCLUDE_SAL_COMMON and SELECT_SNS_SERVER
components.
The INCLUDE_SAL_CLIENT, INCLUDE_SAL_SERVER, and INCLUDE_SNS
components need to be present in a system in order for SAL to work properly. They
do not need to be in the kernel. Normally they will reside on different memory
spaces, possibly on different instances of the system. Therefore, there can be
different scenarios for the configuration of SAL:
1. All three components reside in the same kernel.
2. The SNS is in the kernel and the Client and Server are in different memory
space.
3. The SNS, the client and server are all in user space, but in different memory
spaces.
4. The SNS is in user space and either the client or the server are in the kernel.
5. The SNS is in user space and the client and the server are in the same user
space different from SNS.
There can be several instances of clients in one node, and also different instances
of servers libraries.
There must be one and only one instance of the SNS in the same node. If it resides
in user space, it has to be in a separate RTP.
Each node that participates in using distributed named sockets must have an SNS
server running on that node (either kernel or user space).

Socket Application Library Server

The INCLUDE_SAL_SERVER component pulls in modules that implement the


socket application library client. For more information, see Socket Application
Library Client, p.226.
This component has no configuration parameters and requires the
INCLUDE_SAL_COMMON and SELECT_SNS_SERVER components.

226
11 Creating Network Applications as RTPs
11.4 Using Socket Connections with RTPs

Socket Name Service Server in Kernel

The INCLUDE_SNS component implements the socket name service server in


kernel applications. For more information, see Socket Application Library Client,
p.226.This component requires the INCLUDE_SAL_SERVER,
INCLUDE_SNS_COMMON, and INCLUDE_UN_COMP components. It also
excludes the INCLUDE_SNS_RTP, INCLUDE_SNS_MP, and
INCLUDE_SNS_MP_RTP components. The INCLUDE_SNS component contains the
following configuration parameters:

SNS_PRIORITY

Synopsis: Socket Name Service task (execution) priority.


Default: 50

SNS_STACK_SIZE
11
Synopsis: Socket Name Service task stack size.
Default: 20000

SNS_LISTEN_BACKLOG

Synopsis: Socket Name Service listen sockets backlog size.


Default: 5

Socket Name Service Server in RTP

The INCLUDE_SNS_RTP component implements the socket name service server in


RTPs. Only one SNS instance should run in the a node. Therefore, if no RTP is
available the default would be the kernel. If RTP is available the SNS must run in
a separate RTP.
This component is made of a simple configlette, which launches the SNS daemon
as an RTP executable. It assumes the executable is in a known location, specified
by the SNS_PATHNAME parameter. The SNS_PRIORITY and SNS_STACK_SIZE
parameters should normally use their default values.
The INCLUDE_SNS_RTP component requires the INCLUDE_RTP,
INCLUDE_SNS_RTP_HOOK, INCLUDE_UN_COMP, and INCLUDE_ROMFS. It also
excludes the INCLUDE_SNS, INCLUDE_SNS_MP_RTP, and INCLUDE_SNS_MP
components.

227
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The INCLUDE_SNS_RTP component contains the following configuration


parameters:

SNS_PATHNAME

Synopsis: Socket Name Service pathname.


Default: "/romfs/snsServer.vxe"

SNS_PRIORITY

Synopsis: Socket Name Service task (execution) priority.


Default: 50

SNS_STACK_SIZE

Synopsis: Socket Name Service task stack size.


Default: 20000

SNS_LISTEN_BACKLOG

Synopsis: Socket Name Service listen sockets backlog size.


Default: 5

Socket Name Service Show Routine

The INCLUDE_SNS_SHOW component implements the socket name service show


routine. This component requires the INCLUDE_SAL_COMMON and
INCLUDE_SNS_COMMON components.

11.4.2 Using the SAL Library

The Socket Application Library (SAL) provides support routines to applications


that use sockets to communicate across RTP boundaries or across the boundary
between an RTP and a kernel task. Using the SAL infrastructure, you can more
quickly build socket-based client-server applications, and, most likely, with less
code than if you had implemented the infrastructure yourself. SAL-based
applications can also use a service naming capability, such as SNS (Socket Name
Service) to allow a client application to establish communication with a server
application without having to know the socket addresses used by the server.

228
11 Creating Network Applications as RTPs
11.4 Using Socket Connections with RTPs

The VxWorks SAL implementation supports the AF_LOCAL address family and
the SOCK_SEQPACKET socket type. For additional information on SAL, see the
salClient and salServer reference entries.
VxWorks supports a SAL client and a SAL server in both the kernel space and the
user space.

NOTE: Any client or server application that uses SAL’s service naming capabilities
requires the presence of a Socket Name Service (SNS) server.

Using an SAL Client

SAL client capabilities are available in both kernel space and user space.
To use the SAL client in kernel space:
1. Include the file dsi/salClient.h in source code that uses the SAL client API.
11
2. Include the INCLUDE_SAL_CLIENT component when building the kernel.
To use the SAL client in user space:
1. Include the file dsi/salClient.h in source code that uses the SAL client API.
2. Link in the user-space version of libdsi.a when building the RTP.

Using an SAL Server

SAL server capabilities are available in both kernel space and user space.
To use the SAL server in kernel space:
1. Include dsi/salServer.h in source code that uses the SAL server API.
2. Include the INCLUDE_SAL_SERVER component when building the kernel.
To use the SAL server in user space:
1. Include the file dsi/salServer.h in source code that uses the SAL server API.
2. Link in the user-space version of libdsi.a when building the RTP.

229
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

11.4.3 Using SNS Clients and Servers

VxWorks supports an SNS client and an SNS server in both the kernel space and
the user space. The SNS show capability is supported in kernel space only.

NOTE: Because SNS depends on COMP-based sockets, SNS offers local


name-space services only. Thus, the current SNS implementation does not offer
services to clients on remote nodes. In addition, the SNS client and server are not
network applications. Using them does not require that you include a network
stack in your image.

Configuring an SNS Server

You can set up an SNS server to run in either the kernel space or in user space. You
should not set up more than one SNS server on a single VxWorks target. To set up
an SNS server task that runs in kernel space, include the INCLUDE_SNS
component when building the kernel. To set up an SNS server RTP that runs in
user space:
1. Include the INCLUDE_SNS_RTP component when building the kernel.
2. Include the snsServer.vxe executable in the ROM file system when building a
bootable application image. To create this executable, build the directory:

installDir/vxworks-6.n/target/usr/apps/dsi/snsd

Monitoring an SNS Server

To check that SAL-based services have correctly registered with the SNS server,
you can use the SNS show functionality. Keep in mind that this functionality is
supported in the kernel space only. To configure a VxWorks image to include
support for the SNS show capability:
1. Include the INCLUDE_SNS_SHOW component when building the kernel.
2. Run snsShow command from the shell. This command displays information
on all server applications that have registered with SNS. If no server
applications are registered, a message reports the fact.

230
12
Working with Internet and
Local Domain Sockets

12.1 Introduction 231


12.2 Types of Sockets 233
12.3 Configuring VxWorks for Sockets 235
12.4 Using BSD Sockets under VxWorks 238
12.5 Working with Local Domain Sockets 240
12.6 Working with Internet Domain Sockets 242

12.1 Introduction
This chapter describes how to use the standard BSD socket interface for Internet
domain sockets on a target running the Wind River Network Stack.
Some mention is made of routing sockets and local domain sockets. For detailed
information on the following related topics, refer to the appropriate chapters:

Using the Socket Application Library (SAL), see 11.4 Using Socket Connections
with RTPs, p.223.

Writing applications using sockets, see 13. Writing Sample Applications
Using Sockets.

Using zbuf sockets, see 14. Using Fast UDP and Zbuf Sockets.

231
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


Using routing sockets, see 15. Working with Routing Sockets.

Adding socket-support code to a new network service or protocol, see
22.4 Adding a Socket Interface to Your Service, p.520.

VxWorks Environment-Specific Socket Issues

Although the Wind River Network Stack is fully compatible with the BSD socket
interface, the particulars of the VxWorks environment do affect how you use
sockets. Specifically, the globally accessible file descriptors available in the
task-independent address space of the VxWorks kernel or a VxWorks RTP require
that you take extra precautions when closing a file descriptor.
You must make sure that one task does not close the socket descriptor on which
another task is pending during an accept( ). Although the accept( ) on the closed
descriptor sometimes returns with an error, the accept( ) can also fail to return at
all. Thus, if you need to asynchronously close the descriptor for a socket
connection, you will probably need to set up a semaphore-based locking
mechanism that prevents the close while an accept( ) is pending on the descriptor.

Essential Background Reading

The focus of this chapter is the introduction of the particulars of the Wind River
Network Stack sockets implementation. Teaching you how to work with sockets
in general is beyond the scope of this chapter. Fortunately, the necessary
information is publicly available in RFCs and a variety of online documents that
you can discover using a Web search.
For IPv6 sockets in particular, read RFC 3493: Basic Socket Interface Extensions for
IPv6 and RFC 3542: Advanced Sockets API for IPv6. The Wind River Network Stack
Socket implementation supports these RFCs. It does not now support any of
proposals published only in the Internet drafts.

NOTE: The update to RFC 3542 has changed some of the definitions in a
non-backward compatible way. The IPv6 APIs have changed as per the updated
RFC. For more information, see the release notes and RFC 3542.

232
12 Working with Internet and Local Domain Sockets
12.2 Types of Sockets

Include Files Referenced in this Chapter

This chapter makes reference to the include files, socket.h, in.h, in6.h, and tcp.h.
The full pathnames of these files are as follows:

installDir/vxworks-6.n/target/h/wrn/coreip/sys/socket.h

installDir/vxworks-6.n/target/h/wrn/coreip/netinet/in.h

installDir/vxworks-6.n/target/h/wrn/coreip/netinet6/in6.h
■ installDir/vxworks-6.n/target/h/wrn/coreip/netinet/tcp.h

12.2 Types of Sockets


The Wind River Network Stack supports a standard socket interface to TCP, UDP,
and SCTP. Using these standard BSD sockets, you can: 12

Communicate with other processes.

Access the IP multicasting functionality.

Review and modify the routing tables.

Internet Domain Sockets

Internet domain socket connections provide a communication mechanism that is


homogeneous across diverse operating systems. Applications typically use sockets
in the Internet domains to exchange information with peers on remote host
systems. You can also use sockets in this domain to access the stack’s multicasting
functionality.
In the Internet domains, the VxWorks socket support functions let you define
socket endpoints using either IPv4 or IPv6 addresses.

Sockets in the IPv4 Internet communications domain, AF_INET, bind to names
defined in terms of an IPv4 address and a port number.

Sockets in the IPv6 Internet communications domain, AF_INET6, bind to
names defined in terms of an IPv6 address and a port number.
As much as possible, the socket API is IPv6/IPv4 agnostic. Thus, the sockLib calls
have been modified internally to respond appropriately to an IPv6 address, but
they do this only if the socket( ) call that created the socket specified the IPv6

233
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

address family. In addition, to pass in an IPv6 address, you need to use a


sockaddr_in6 structure that you have cast as a sockaddr structure. Despite this
adaptation to IPv6 addresses, there are some socket-mediated services, such as
multicasting, that are strongly impacted.

Routing Sockets

Sockets in the routing communications domain, AF_ROUTE, communicate with


the local route table. Use a routing socket to make or monitor changes to the
contents of the route table.
The host stack route table ranks multiple same-destination routes by age. For this
route table, the oldest route to a destination serves as the representative route to
that destination. The representative route is the route presented to IP when it
queries the route table for a route to a destination.
If you rebuild the network stack with -DROUTER_STACK, it creates a router stack.
The route table in a router stack ranks multiple same-destination routes by a
user-assigned weight. If there are multiple same-destination routes, the lowest
weight entry is used as the representative route. If this representative route is
deleted, the next lowest-weight route becomes the new representative route.
Building the network stack with -DROUTER_STACK also enables support for the
extended routing socket message set. The additional routing socket message types
facilitate cooperation among protocols that might need to share the route table that
stores redundant entries.
For more information, see 15. Working with Routing Sockets.

Local Domain Sockets

Sockets in the local communications domain, AF_LOCAL, bind to names modeled


after the names of files in a file system. No actual file system is required to use
AF_LOCAL sockets. Socket names are handled internally by the COMP protocol.
This protocol provides an optimized transport for same-node communication
among tasks. This communication method is able to cross into RTPs and the
kernel. Thus, you can use it to communicate among tasks running in different
RTPs. You can also use it to communicate between a task running in an RTP and a
task running in the kernel. For more information, see 12. Working with Internet and
Local Domain Sockets.

234
12 Working with Internet and Local Domain Sockets
12.3 Configuring VxWorks for Sockets

NOTE: Although the COMP protocol is mentioned in this manual, you should
know that COMP is independent of the network stack. Thus, if you need to use
COMP, you do not need to include a network stack in your VxWorks image.

12.3 Configuring VxWorks for Sockets


The Wind River Network Stack supports the following configuration components
usable extensible standard socket interface, and standard BSD Internet domain
sockets:
■ Socket API
■ Socket API System Call Support
■ BSD Socket Support
12
These components are listed under the
Network Components > Network Socket Components folder in Workbench.
The extensible interface is the core component within this system. It mediates
access to registered socket back ends. It also provides an API that you can use to
register a proprietary socket back end for any new protocols or applications that
you develop.

NOTE: This section focuses on components associated with network-related


sockets (that is, Internet sockets and routing sockets). Not described here is the
INCLUDE_UN_COMP component, which pulls in an implementation of the COMP
protocol. This protocol is required for AF_LOCAL domain SOCK_SEQPACKET type
sockets.

Socket API

The INCLUDE_SOCKLIB component pulls in sockLib, a VxWorks library that


implements the standard socket interface layer. This layer mediates access to
registered socket back ends. Including any of the other sockets components
automatically registers their socket back ends with the standard socket interface
layer.
For information on how to register additional socket back ends, see 22. Integrating
a New Network Service, and the sockLib reference entry.

235
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Socket API System Call Support

The INCLUDE_SC_SOCKLIB component pulls in sockScLib, which provides


socket system call support in RTPs. It is included automatically when RTP
support, INCLUDE_RTP, is included.
This component requires the following components:
■ Socket API
■ INCLUDE_RTP

For information on how to register additional socket back ends, see 22. Integrating
a New Network Service, and the sockLib reference entry.

BSD Socket Support

The INCLUDE_BSD_SOCKET component pulls in bsdSockLib and other modules


needed in support of standard BSD Internet Domain sockets. These are sockets
whose end points are defined in terms of IPv4 or IPv6 addresses. For more
information on working with BSD Internet domain sockets, see the bsdSockLib
reference entry and 12.3 Configuring VxWorks for Sockets, p.235.
This component requires the INCLUDE_SOCKLIB and INCLUDE_NET_POOL. This
component contains the following parameters:

MAXSOCKBUF_CFG

Synopsis: Specifies the maximum socket buffer size.


Default: (SB_MAX)?(SB_MAX) : (256*1024)

SOCKBUF_WASTE_FACTOR_CFG

Synopsis: Specifies the sb_efficiency value for sbreserve( ) calls.


Default: 8

Before using a new socket, the stack reserves the specified number of buffers
for the socket.

SOMAXCONN_CFG

Synopsis: Specifies the maximum pending socket connections queue size.


Default: (SOMAXCONN) ? (SOMAXCONN) : 128

236
12 Working with Internet and Local Domain Sockets
12.3 Configuring VxWorks for Sockets

SO_LINGER_INFINITE_CFG

Synopsis: Use traditional VxWorks SO_LINGER time-out.


Default: FALSE

Use this parameter to restore the behavior previously associated with the
SO_LINGER option.
In earlier releases, the l_linger member of the struct linger argument to the
SO_LINGER option was significant only insofar as it was zero or nonzero. If
SO_LINGER was enabled and the l_linger was zero, a close( ) on the socket
descriptor resulted in dropping the connection (for TCP, a RST segment was
sent to the peer). If SO_LINGER was enabled and the l_linger value was
nonzero, then the call to close( ) would block until either all outstanding data
(and TCP FIN) had been acknowledged by the peer, or until the protocol timed
out and dropped the connection itself.
More typically, the close( ) call should return if l_linger seconds elapsed
before either all outstanding data and FIN were acknowledged or the
connection was dropped by the protocol. VxWorks previously did not support 12
such time-outs. Now it does, by default. The previous VxWorks behavior can
be restored by setting the SO_LINGER_INFINITE_CFG parameter to TRUE.
In the current release, when the timeout expires on a close( ) against a socket:

If SO_LINGER_INFINITE_CFG is FALSE.

If SO_LINGER is enabled with a non-zero timeout.

If the timeout expired without the connection successfully disconnecting.
What happens next depends upon SO_LINGERRESET, a VxWorks-specific
socket option. By default, SO_LINGERRESET is not enabled, and the protocol
(TCP) continues with the graceful shutdown attempt. If SO_LINGERRESET is
enabled, then the connection is aborted (sending a TCP RST segment to the
peer). In either case, the close( ) call returns ERROR, and errno is set (usually
to ETIMEDOUT, unless the protocol itself dropped the connection, in which
case errno might indicate a “soft” error). The socket has been closed, and you
can no longer use the socket descriptor. For more information, see the
setsockopt( ) reference entry.

237
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

12.4 Using BSD Sockets under VxWorks


A socket is defined as a communications endpoint to which you can bind a name.
This name makes it possible to access the socket. Implicit in the idea of an endpoint
is the notion of a space that contains the endpoint. By convention, the space
containing a socket is called a communications domain. Valid names for a socket
are defined in terms of the socket’s communication domain.
This definition of a socket indicates that the socket metaphor is not necessarily
limited to a programming environment. For example, you can think of a telephone
as a socket. The telephone is a communications endpoint to which the phone
company has bound a name, a telephone number. This telephone number has been
chosen from the communications domain of valid telephone numbers.
Within a programming environment, a socket is often implemented as a descriptor
to which you bind a name. Associated with the descriptor are routines that can
read or write information to or from the descriptor. The names that you can assign
to the descriptor derive from the communications domain for the socket.

Supported Communications Domains

BSD UNIX supports a long list of communications domains for its sockets. Of
these, only the following are supported under VxWorks:

the IPv4 Internet communications domain (AF_INET)

the IPv6 Internet communications domain (AF_INET6)

the routing communications domain (AF_ROUTE)

local domain sockets for interprocess communication (AF_LOCAL)

the Transparent Inter-Process Communication domain (AF_TIPC)

the Mobile IPv6 domain (AF_MOBILITY)

NOTE: Neither the AF_TIPC domain sockets nor the AF_MOBILITY domain sockets
are described in this manual. For information on AF_TIPC sockets, see the Wind
River TIPC for VxWorks 6 Programmer's Guide. For information on AF_MOBILITY
sockets, see the Wind River Mobile IPv6 for VxWorks 6 Programmer's Guide.

Sockets in the IPv4 Internet communications domain, AF_INET, bind to names


defined in terms of an IPv4 address and a port number. Similarly, sockets in the
IPv6 Internet communications, AF_INET6, domain bind to names defined in terms
of an IPv6 address and a port number. Applications typically use sockets in the
Internet domains to exchange information with peers on remote host systems. It is
possible to use an Internet domain socket to communicate with a peer on the local

238
12 Working with Internet and Local Domain Sockets
12.4 Using BSD Sockets under VxWorks

host. Under VxWorks, there are more efficient mechanisms, such a AF_LOCAL
sockets, TIPC, and message queues, for communications among local tasks.
Sockets in the routing communications domain, AF_ROUTE, communicate with
the local route table. You can use a routing socket to make or monitor changes to
the contents of the local route table.
Under VxWorks, sockets in the local communications domain, AF_LOCAL, bind to
names modeled after the names of files in file system. No actual file system is
required to use AF_LOCAL sockets. Under VxWorks, local domain socket names
are handled by the proprietary Connection-Oriented Message Passing (COMP)
protocol.

Supported Socket Types

Associated with socket-based communication is the idea of socket type. A socket’s


type describes the communication style supported by that socket. Under
VxWorks, the supported socket communication styles or types are as follows: 12

SOCK_DGRAM – bidirectional, unreliable, not sequenced, possibly


duplicated, message oriented
SOCK_STREAM – bidirectional, reliable, sequenced, non-duplicated, stream
oriented
SOCK_SEQPACKET – bidirectional, reliable, sequenced, non-duplicated,
message oriented
SOCK_RDM – bidirectional, reliable, not sequenced, possibly duplicated,
message oriented. This type is supported for AF_TIPC sockets only and is not
discussed further in this manual. For more information, see Wind River TIPC
for VxWorks 6 Programmer’s Guide.
The SOCK_DGRAM communication type describes a connectionless
communication style based on an exchange of datagrams. This style of
communication is analogous to an exchange of letters (datagrams) using a postal
service. When using this communication style, the connection is not monitored,
and you will not necessarily notice whether a datagram is lost. This is analogous
to losing a letter handed to a postal service. If some agent, such as natural disaster,
destroys your letter in transit, you will not necessarily know. Under VxWorks, the
implementation of Internet domain datagram sockets is done on top of UDP, a
transport layer protocol of the TCP/IP stack.

239
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The SOCK_STREAM communication type describes a connection-oriented


communication style characterized by the exchange of a continuous stream of
data. This style of communication is analogous to a phone conversation. When
using this communication style, the connection is monitored, and you are
informed if the connection is broken. This is analogous to losing the connection
during a phone connection and getting a warning signal on the line. Under
VxWorks, the implementation of Internet domain stream sockets is done on top of
TCP, a transport layer protocol of the TCP/IP stack.
The SOCK_SEQPACKET type describes a communication style that is both
connection oriented and message oriented (as opposed to stream oriented). Being
message oriented means that users of the SOCK_SEQPACKET type socket receive
data as discrete messages instead of as a stream of data. This socket type is
supported for sockets in the AF_LOCAL domain only. Under VxWorks, AF_LOCAL
domain sockets are implemented on top of a proprietary protocol known as
COMP. This protocol provides support for the SOCK_SEQPACKET style of
communication.

Raw Sockets for Socket Type “Other”

BSD sockets support an additional socket communication type known as the raw
socket. The raw socket is a socket with an unspecified communication style. Its
communication characteristics (reliable or not, sequenced or not, and so on) are
determined by the services provided by the domain and protocol that you specify
when you create the socket. Under VxWorks, the primary use of the raw socket is
within the AF_ROUTE domain, where sockets provide a mechanism by which
host-local tasks can monitor and make changes in the contents of the route table.

12.5 Working with Local Domain Sockets


Under VxWorks, local domain sockets (AF_LOCAL sockets) are based on a protocol
known as COMP. This protocol provides support for the SOCK_SEQPACKET
communication style, which is bidirectional, reliable, and message-based.
The current release provides support for the standard socket APIs: socket( ),
bind( ), listen( ), and so on. Also supported are the standard file system APIs:
read( ), write( ), close( ), ioctl( ), and select( ).

240
12 Working with Internet and Local Domain Sockets
12.5 Working with Local Domain Sockets

Because the AF_LOCAL/COMP sockets use a connection-oriented communication


style, you must complete a bind-listen-connect-accept sequence before you can
transmit data on the socket. To handle the transmission and reception of data on
the socket, use the send( ) and recv( ) routines. The setsockopt( ), getsockopt( ),
and ioctl( ) are supported, but with a minimal set of options.

Including Support for Local Domain Sockets

To create a VxWorks image that includes support for local domain sockets, you
must include the INCLUDE_UN_COMP component. This component pulls in the
COMP implementation. Note that this component is not a network stack
component and that COMP is independent of the network stack. You can include
COMP in a VxWorks image and use even if you do not include a network stack.

Setting up an Local Domain Socket

Under VxWorks, COMP manages the name space for an AF_LOCAL domain
socket. Thus, when creating names for AF_LOCAL sockets, you must conform to
the expectations of the COMP system, which is a name in the format: 12

/comp/socket/0xNumber
In this name, treat the /comp/socket/ part as an invariable prefix. Treat the
0xNumber part as a string representation of a 16-bit number in hexadecimal format.
No other format is supported. This name is used when you bind( ) a name to a
socket and when you connect( ) to a listening socket. This name is supplied using
a sockaddr_un structure:
struct sockaddr_un /* LOCAL (UNIX) family address */
{ /* --------------------------- */
uint8_t sun_len; /* 0x00: structure size */
uint8_t sun_family; /* 0x01: address family */
char sun_path [104]; /* 0x02: actual address */
}; /* 0x6A: TOTAL SIZE */

This structure is defined in un.h. You will need to include un.h as well as
sockLib.h, the include file for the standard socket API:
sockLib.h /* standard socket API */
sys/un.h /* struct sockaddr_un definition */

To set up a sockaddr_un structure for an AF_LOCAL socket:


mySockaddr_un.sun_len = sizeof (struct sockaddr_un); /* 106 bytes */
mySockaddr_un.sun_family = AF_LOCAL;
bcopy ("/comp/socket/0x1234", mySockaddr_un.sun_path, 20);

241
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

12.6 Working with Internet Domain Sockets


This section tells you how to set up an Internet socket, how to connect it to a peer,
how to exchange data with that peer, and how to shut down that socket when you
are done with it. Also included is a listing of support routines for working with
Internet addresses.

12.6.1 Setting up an Internet Domain Socket under VxWorks

As mentioned above, a socket is a communications endpoint to which you can


bind a name. Under VxWorks, a socket is implemented and managed using a
socket descriptor, to which you can bind a name from the desired domain. To
create a socket descriptor, call socket( ). To configure this socket descriptor for
your particular use of that socket, call setsockopt( ). To bind a name to a socket
descriptor, call bind( ).

Creating a Socket Descriptor

To send and receive data over a socket, you need a socket descriptor. To create a
socket descriptor, call socket( ). As input, a VxWorks socket( ) call expects you to
specify three things:

a communications domain for the socket

a socket type

a protocol type
For the communications domain, specify either AF_INET or AF_INET6, depending
on whether you want a socket in the IPv4 or IPv6 domain. For the socket type, use
SOCK_STREAM to indicate a stream type socket. To indicate a datagram type
socket, use SOCK_DGRAM.
For a stream socket in an Internet domain, you could specify a protocol type of
IPPROTO_TCP or IPPROTO_SCTP. These protocols provide the necessary support
services for a streams type socket in the Internet domains. For datagram sockets,
you could specify a protocol type of IPPROTO_UDP. UDP is the IP protocol that
provides the necessary support services for a datagram type socket in the Internet
domain. You do not typically specify either IPPROTO_TCP or IPPROTO_UDP
explicitly. Instead, you should specify 0 (zero), which tells socket( ) to choose
whatever supporting transport layer protocol is best suited to the requested socket
type and communications domain.

242
12 Working with Internet and Local Domain Sockets
12.6 Working with Internet Domain Sockets

For raw sockets in the Internet domains, a protocol of zero indicates the IP
protocol, IPPROTO_IP. Such a socket gives you direct access to IP. If you want an
Internet domain raw socket into a different protocol, use an appropriate
IPPROTO_name value as defined in in.h. For example, to verify that an IP address
is not already in use, a DHCP server implementation might create a raw socket in
the IPv4 Internet domain and specify a protocol of IPPROTO_ICMP. In the IPv6
Internet domain, it would specify a protocol of IPPROTO_ICMPV6. The server
could then send out an ICMP echo request on the socket to test the address.

Setting Socket Options

After creating a socket descriptor, you want to specify the socket options that
configure the socket for your particular needs. Most options you can handle with
a call to setsockopt( ), although there is one “option” you set with an ioctl( ) call.

NOTE: For information on SO_VSLOCK, a socket option associated with sockets in


a virtual stack instance, see 7.3.4 Using Sockets in Virtual Stacks, p.120 12

Using an ioctl( ) Call to Make the Socket Non-Blocking

To make a socket non-blocking, call ioctl( ) as follows:


on = 1;
if (ioctl (mySocketDescriptor, FIONBIO, (int) &on) == -1) {
your response code for the ioctl call failure
}

Using setsockopt( ) to Set Socket Options

The synopsis for setsockopt( ) is defined as follows:


STATUS setsockopt
(
int s, /* target socket */
int level, /* protocol level of option */
int optname, /* option name */
char * optval, /* pointer to option value */
int optlen /* option length */
)

NOTE: Calling setsockopt( ) is not an absolute necessity. It is possible to use


sockets without setting any socket options if the default options associated with a
stream, datagram, or routing socket are appropriate to your needs. Although it is
a good idea to know the default socket option values (such as SO_LINGER and
SO_REUSEADDR) and their consequences for the behavior of the socket.

243
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This routine sets the options associated with a socket and any underlying protocols
that support the services accessible through the socket. You should make your
setsockopt( ) call before binding a name to a socket. This is because some socket
options affect the outcome of the bind. For example, some socket options let you
restrict the bind to a particular range of port numbers.
The level parameter of a setsockopt( ) call lets you specify whether the option
applies to the socket itself or an underlying protocol. The socket-level options (level
is SOL_SOCKET) are the most generic options and make sense in the context of
many sockets. Names (optname values) for these socket options are defined in
socket.h. In addition to these socket-level options, setsockopt( ) also lets you pass
options through to the underlying protocol or protocols that support and
implement the services accessed through the socket.
For example, there are a large number of options associated with IPv4. To set these
options for IPv4, you would specify a level of IPPROTO_IP. These options control
and configure access to IPv4-supplied functionality such as IPv4-based
multicasting. Names (optname values) for these socket options are defined in in.h.
The setsockopt( ) reference entry describes the most commonly used of the IP
socket options listed above. Paralleling the socket options for IPv4, Wind River
Network Stack also includes support for IPv6 socket options. For IPv6, you would
assign level a value of IPPROTO_IPV6 and use the optname values for these socket
options as defined in in6.h.
Other commonly socket-accessed protocols and options include the IPPROTO_TCP
protocol and the TCP_NODELAY option, which is described in the setsockopt( )
reference entry. Other socket option names for this protocol are defined in tcp.h.
Whether a protocol supports socket access depends on the protocol. For more
information, see the RFCs for the protocol that interests you.

Binding a Name to a Socket

To bind a name to a socket descriptor, call bind( ). As input, a VxWorks bind( ) call
expects you to specify three things:

the socket to which you would bind a name

the name, passed in using a sockaddr structure

the length of the name
As input, bind( ) expects the socket name to be supplied using a pointer to a
sockaddr structure. The layout of the sockaddr structure is not convenient for
setting up all the information needed to specify a socket name in the Internet
communications domain. Instead, you should use either a sockaddr_in structure

244
12 Working with Internet and Local Domain Sockets
12.6 Working with Internet Domain Sockets

or a sockaddr_in6 structure that you cast as a sockaddr structure when you make
the actual bind( ) call. Use the sockaddr_in structure for sockets in the IPv4
Internet communications domain, and the sockaddr_in6 structure for sockets in
the IPv6 Internet communications domain.

NOTE: Sockets in the routing domain, never require an explicit bind( ) call.

Omitting the Bind Call

If you omit the explicit bind( ) call for the socket descriptor that you create, the
internals of your first send through the socket automatically handle the bind( ) for
you. In this case, the port number bound to your socket is chosen for you from
among the unused private port numbers (also known as dynamic or ephemeral
port numbers), which are port 49152 through port 65535. This approach is
acceptable if, as is often the case, your code does not need to know the number of
the port to which its socket is bound.

Letting the System Select Your Port Number 12


If you want to let the system select a port number for you, but you need to know
that number, you must make an explicit bind( ) call. Among its inputs, this call
requires either a sockaddr_in or a sockaddr_in6 structure. To bind to a particular
port explicitly, you would specify particular values in the port and IP address
members of these structures. If you write a zero to these members, the bind( )
selects the values for you. After control returns from bind( ), your code can read
the port number from the sockaddr_in or the sockaddr_in6 structure.

Binding to Well-Known and Registered Ports

In the Internet communications domains, port numbers 0 through 1023 are


reserved for use by well-known services associated with TCP. These are services
such as echo, time, and so on. Ports 1024 through 49151 are reserved for services
registered with IANA. If you were to implement a server for a well-known or
registered service, you would bind your socket to the port assigned to that service,
and then monitor that socket for requests from clients.
For a list of the port assignments for well-known and registered services, see:
http://www.iana.org/assignments/port-numbers
This list is also useful if you are implementing a client of a well-known service. It
tells you the port on the remote site to which you should send requests.
If you need to request a port number assignment for a new service, you can apply
to IANA. You need do that only if you are creating a service that you will to

245
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

publish to the entire Internet. For a service offered within a network throughout
which you can control how port numbers are used, you can choose a private port
number within the range 49152 through 65535.

Setting Up a sockaddr_in Structure to Store an IPv4 Address

The in.h file defines the sockaddr_in structure as follows:


struct sockaddr_in {
u_char sin_len; /* The length of the address. */
u_char sin_family; /* The address family, AF_INET. */
u_short sin_port; /* The port number. */
struct in_addr sin_addr; /* The IP Address. */
char sin_zero[8]; /* Optional mask for address. */
};
struct in_addr {
in_addr_t s_addr;
};

The in_addr_t is an unsigned 32-bit integer.

NOTE: sin_len must be assigned a value. If this is not done prior to calling
sendmsg( ), for example, the call will fail with an EINVAL (0x22) error.

The following code fragment shows one way to set up a sockaddr_in structure for
a server identified by a user-entered text string. This string can contain either a
dot-notation IPv4 address or its user-friendly equivalent name.
struct sockaddr_in serverAddr;

sockAddrSize = sizeof (struct sockaddr_in);


bzero ((char *) &serverAddr, sockAddrSize);
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons (SERVER_PORT_NUM);

if (((serverAddr.sin_addr.s_addr = inet_addr (serverName)) == ERROR) &&


((serverAddr.sin_addr.s_addr = hostGetByName (serverName)) == ERROR))
{
perror ("unknown server name");
close (sFd);
return (ERROR);
}

The inet_addr( ) call converts a dot-notation IPv4 address to a long integer. If that
call fails, the code assumes that the user specified the server by name. To convert
the name to an IPv4 address, the code calls hostGetByName( ). This routine looks
up the name in the host table and returns its IPv4 address. If you configured the
stack to include DNS, hostGetByName( ) uses DNS to get the name if the host
table search fails.

246
12 Working with Internet and Local Domain Sockets
12.6 Working with Internet Domain Sockets

Setting Up a sockaddr_in6 Structure to Store an IPv6 Address

The in6.h file defines the sockaddr_in6 structure as follows:


struct sockaddr_in6 {
u_int8_t sin6_len; /* length of this struct(sa_family_t) */
u_int8_t sin6_family; /* AF_INET6 (sa_family_t) */
u_int16_t sin6_port; /* Transport layer port # (in_port_t) */
u_int32_t sin6_flowinfo; /* IP6 flow information */
struct in6_addr sin6_addr; /* IP6 address */
u_int32_t sin6_scope_id; /* scope zone index */
};
struct in6_addr {
union {
u_int8_t __u6_addr8[16];
u_int16_t __u6_addr16[8];
u_int32_t __u6_addr32[4];
} __u6_addr;
};

Consider the following code fragment:


struct hostent * foundAddress;
struct sockaddr_in6 serverAddr; 12
_res.options |= RES_USE_INET6;
if (((foundAddress = gethostbyname (serverName )) == NULL ) &&
((foundAddress = gethostbyaddr (serverName, 0, AF_INET6 )) == NULL ))
{
perror ("unknown server name");
close (sFd);
return (ERROR);
}
else
{
bzero ((char *) &serverAddr, sizeof (struct sockaddr_in6);
serverAddr.sin6_len = sizeof (struct sockaddr_in6);
serverAddr.sin6_family = AF_INET6;
serverAddr.sin_port = htons (SERVER_PORT_NUM);
serverAddr.sin6_scope_id = htonl (2);
bcopy ( foundAddress->h_addr, serverAddr.sin6_addr,
foundAddress->h_length );
hostentFree( foundAddress );
}

The code above assumes serverName contains either the name of the server or a
string representation of its IPv6 address. This guarantees success for either the
gethostbyname( ) or gethostbyaddr( ) calls if the code received a valid host name
or address and if it has access to a well informed host table or a functioning DNS
implementation.
The code fragment then initializes the address fields. Some of them, sin6_len and
sin6_family are set to well known values for all IPv6 addresses. Others, sin_port
and sin6_scope_id, are set to known values for this application. The scope id is a

247
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

32-bit integer that identifies a set of interfaces as appropriate for the scope of the
address carried in the sin6_addr field.
The code fragment then copies the address information the returned hostent
structure and then calls hostentFree( ) to free the hostent structure. This structure
was allocated internally by either the gethostbyname( ) or gethostbyaddr( ) call.
Freeing this structure is the responsibility of any code that calls gethostbyname( )
or gethostbyaddr( ).

NOTE: The code fragment shown above includes the line:


_res.options |= RES_USE_INET6;

This sets a global variable that configures gethostbyname( ) or gethostbyaddr( ) to


return IPv6 addresses.

12.6.2 Creating the Connection for Internet Domain Stream Sockets

Sending and receiving data through a socket is more or less the same whether the
socket is a stream or datagram socket. Before you can exchange data over a stream
socket, you must establish a connection. The routines used to create this
connection assume a client server relationship.
A client wishing to establish a connection with a server calls connect( ) on a socket
it has created to communicate with its server. Whether the connect( ) call blocks if
a connection is not immediately available depends on how you have configured
the socket (see Setting Socket Options, p.243).
If the socket is non-blocking, control returns from connect( ) immediately. If a
connection was established, the returned routine value was OK. Otherwise, the
routine returns a ERROR and sets errno to EINPROGRESS or EALREADY. You can
repeat the connect( ) call until you establish a connection. Upon establishing the
connection, the returned routine value will still be ERROR, but the errno value will
be EISCONN.

NOTE: As an alternative to connect( ), consider connectWithTimeout( ). For more


information, see the connectWithTimeout( ) reference entry.

On the server side, the server needs to have called listen( ) on the socket it has
created to communicate with clients. The server can then call accept( ) on the
socket to indicate that it accepts the socket connection. This sends a message to the
client that indicates that the connection is established.

248
12 Working with Internet and Local Domain Sockets
12.6 Working with Internet Domain Sockets

When the call returns from the accept( ), the routine value is a new socket
descriptor. Using this new descriptor, the server can exchange messages with the
client that requested the connection. The new socket descriptor makes it possible
to queue the accepted connection onto another task for processing. This allows the
server to loop back to accept the next connection request (if any) queued on the
original socket.
Servers typically call accept( ) from within a forever loop. If there is no connection
request pending, the accept( ) blocks until a connection request arrives on the
socket. If this is unacceptable, configure the socket to be non-blocking (see Setting
Socket Options, p.243). If there is no connection request on the socket, and the socket
is non-blocking, the accept( ) call returns ERROR.

Using a connect( ) Call with a Datagram Socket

Calling connect( ) for a datagram socket does not create a monitored connection to
the specified destination. It does configure the socket to assume the specified
destination for all messages read from and written to the socket. This makes it
possible to call send( ) and recv( ) on the datagram socket instead of sendto( ) and 12
recvfrom( ).

12.6.3 Sending and Receiving Data Using Internet Domain Sockets

The mechanics of sending and receiving data on a socket are quite simple. Forming
or interpreting the message can be a bit more complicated, and it varies according
to the protocol assumed by the sender and recipient. For the most part, the
mechanics of forming protocol-appropriate messages is beyond the scope of this
document. The only exception is the discussion of routing socket messages
provided in 15. Working with Routing Sockets.

Sending and Receiving Data without Regard to the Control Data

If you have called connect( ) on a socket descriptor, or have received the socket
descriptor from an accept( ) call, the socket is already configured with the address
of the communication partner on the other side of the socket. This is also true for
all client sockets in the routing domain. For such a socket descriptor, you can
exchange messages over the socket using send( ) and recv( ) or the generic write( )
or read( ) routines. All four of these routines are typically used with stream
sockets. If you called connect( ) on a datagram socket, you can use these routines
to communicate over a datagram socket.

249
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

For a datagram socket for which you have not called connect( ), you need to
explicitly identify communications partner on the other side of the socket. In this
situation, you can use sendto( ) and recvfrom( ) to exchange messages over the
socket.

Accessing and Setting the Control Data for a Socket Message

In addition to the send and receive routines mentioned above, sockLib also
supports the routines, sendmsg( ) and recvmsg( ). These routines let you work
with the entirety of the socket message – both its message header and its data
payload. The message header is accessible using a msghdr structure, which is
defined in socket.h as:
/*
* Message header for recvmsg and sendmsg calls.
* Used value-result for recvmsg, value only for sendmsg.
*/
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
int msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
socklen_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};

When using the sendmsg( ) and recvmsg( ) routines with a datagram socket for
which you have not called connect( ), use the msg_name field to specify the
address of the communication partner on the other side of the socket.
The advantage of using sendmsg( ) and recvmsg( ) is that it makes it easier to
access the control (ancillary) information associated with the message and not
merely the message payload data. The msg_control field points to a buffer
containing the ancillary data. The data objects in this control buffer are accessible
using cmsghdr structures, which socket.h defines as:
/*
* Header for ancillary data objects in msg_control buffer.
* Used for additional information with/about a datagram
* not expressible by flags. The format is a sequence
* of message elements headed by cmsghdr structures.
*/
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by u_char cmsg_data[]; */
};

250
12 Working with Internet and Local Domain Sockets
12.6 Working with Internet Domain Sockets

To make it easier to work with these message headers, socket.h defines the macros
CMSG_FIRSTHDR( ), CMSG_DATA( ), and CMSG_NXTHDR( ) as follows:
/* given pointer to struct cmsghdr, return pointer to data */
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + \
_ALIGN(sizeof(struct cmsghdr)))

/* given pointer to struct cmsghdr, return pointer to next cmsghdr */


#define CMSG_NXTHDR(mhdr, cmsg) \
(((caddr_t)(cmsg) + _ALIGN((cmsg)->cmsg_len) + \
_ALIGN(sizeof(struct cmsghdr)) > \
(caddr_t)(mhdr)->msg_control + (mhdr)->msg_controllen) ? \
(struct cmsghdr *)NULL : \
(struct cmsghdr *)((caddr_t)(cmsg) + _ALIGN((cmsg)->cmsg_len)))

#define CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control)

This level of access is convenient when implementing a service such as ping( ). If


you are merely exchanging data and not interested in the control data, you a
probably better off using the send( )/sendto( )/write( ) and
recv( )/recvfrom( )/read( ) routines.
12

12.6.4 Closing or Shutting Down an Internet Domain Socket Connection

When a client or server has decided that it is time to end its conversation with the
communication partner, it can break the connection by calling shutdown( ) or its
generic near equivalent, close( ). Of the two routines, shutdown( ) provides the
greater flexibility. Using shutdown( ), you can break the send side of the socket
connection, the receive side of the socket connection, or both.
If you shutdown both the send and receive sides of the socket connection, and the
socket is configured with the SO_REUSEADDR option set, you can reuse the socket
to support a connection with a different client or server.

! WARNING: Before shutting down a socket connection, do not shutdown the


connection on which another task is pending during an accept( ). Although the
accept( ) on the closed connection sometimes returns with an error, the accept( )
can also fail to return at all. Thus, if you need to asynchronously close the
connection, you will probably need to set up a semaphore-based locking
mechanism that prevents the close while an accept( ) is pending on the descriptor.

There can be a degree of latency associated with closing a socket connection if you
enabled the SO_LINGER socket option and set the l_linger member of the
struct linger argument.

251
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

In earlier releases, the l_linger member of the struct linger argument to the
SO_LINGER option was significant only insofar as it was zero or nonzero. If
SO_LINGER was enabled and the l_linger was zero, closing a socket resulted in
dropping the connection (for TCP, a RST segment was sent to the peer). If
SO_LINGER was enabled and the l_linger value was nonzero, then the call that
closed the socket connection would block until either all outstanding data (and
TCP FIN) had been acknowledged by the peer, or until the protocol timed out and
dropped the connection itself.
More typically, a socket close( ) call should return if l_linger seconds elapsed
before either all outstanding data and FIN were acknowledged or the connection
was dropped by the protocol. VxWorks previously did not support such time-outs.
Now it does, by default. You can restore the previous VxWorks behavior by setting
the SO_LINGER_INFINITE_CFG parameter to TRUE.
In the current release, the timeout expires on a close( ) against a socket:
■ If SO_LINGER_INFINITE_CFG is FALSE.
■ If SO_LINGER is enabled with a non-zero timeout.
■ If the timeout expired without the connection successfully disconnecting.
What happens next depends upon SO_LINGERRESET, a VxWorks-specific socket
option. By default, SO_LINGERRESET is not enabled, and the protocol (TCP)
continues with the graceful shutdown attempt. If SO_LINGERRESET is enabled,
then the connection is aborted (sending a TCP RST segment to the peer). In either
case, the close( ) call returns ERROR, and errno is set (usually to ETIMEDOUT,
unless the protocol itself dropped the connection, in which case errno might
indicate a “soft” error). The socket has been closed, and you can no longer use the
socket descriptor. For more information, see the setsockopt( ) reference entry.
While the socket is in its period of graceful shutdown, it is referred to as being in a
TIME_WAIT state. To bypass the TIME_WAIT state, turn off the SO_LINGER
option. This lets you bind socket to the same port and reconnect to the same
destination even if the TIME_WAIT has not yet expired. To turn off the SO_LINGER
option, use code similar to the following:
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;

if ( setsockopt (
newConnection, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger)
)
== ERROR ) {
perror ("setsockopt SO_LINGER failed");
return (ERROR);
}

252
12 Working with Internet and Local Domain Sockets
12.6 Working with Internet Domain Sockets

12.6.5 Support Routines for Working with Internet Addresses

If you are writing a socket-based application, your users will expect to be able to
enter host names as well as IPv4 or IPv6 address strings. In addition, when
presenting socket-related information on the destination, users will expect host
names and not numerical expressions of the IPv4 or IPv6 address strings. To
convert host names to their corresponding IP addresses and back, the Wind River
Network Stack provides hostLib, inetLib, and the following routines:
getaddrinfo( ) – node name-to-address translation
getnameinfo( ) – translate a socket address to a node name and service name
gethostbyname( ) – name-to-address translation routine
gethostbyaddr( ) – address-to-name translation routine
getsockname( ) – get a socket name
getpeername( ) – get the name of a connected peer
These routines check first in the local host table to retrieve the requested
information. If the host table cannot supply the information, they access DNS.
Among the hostLib routines, note that hostGetByName( ) and hostGetByAddr( ) 12
are IPv4-only. The same is true for the inetLib routines, inet_ntoa( ) and
inet_addr( ). If you are writing an application that must work in both the IPv4 and
IPv6 Internet domains, you should probably avoid using IPv4-only routines.

253
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

254
13
Writing Sample Applications
Using Sockets

13.1 Introduction 255


13.2 Writing Applications Using Datagram Sockets (UDP) 255
13.3 Writing Applications Using Stream Sockets (TCP) 266

13.1 Introduction
This chapter provides code for sample applications using datagram (UDP) sockets
and TCP stream sockets.

13.2 Writing Applications Using Datagram Sockets (UDP)


This section provides two code examples. The first implements a simple
client-server communication system using IPv4 datagram (UDP) sockets. The
second demonstrates how to use IPv4 UDP sockets to handle multicasting.

255
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

13.2.1 Using a Datagram Socket to Implement a Client-Server System

The following code example uses a client-server communication model. The server
communicates with clients using datagram-oriented (UDP) sockets. The main
server loop, in udpServer( ), reads requests and optionally displays the client’s
message. The client builds the request by prompting the user for input. Note that
this code assumes that it executes on machines that have the same data sizes and
alignment.

NOTE: sin_len must be assigned a value:


addr.sin_len = sizeof (struct sockaddr_in);

If this is not done prior to calling sendmsg( ) for example, the call will fail with an
EINVAL (0x22) error.

Example 13-1 IPv4 Datagram Sockets (UDP)

/* udpExample.h - header used by both UDP server and client examples */

#define SERVER_PORT_NUM 5002 /* server's port number for bind() */


#define REQUEST_MSG_SIZE 1024 /* max size of request message */

/* structure used for client's request */

struct request
{
int display; /* TRUE = display message */
char message[REQUEST_MSG_SIZE]; /* message buffer */
};

/* udpClient.c - UDP client example */

/*
DESCRIPTION
This file contains the client-side of the UDP example code.
The example code demonstrates the usage of several BSD 4.4-style
socket routine calls.
*/

/* includes */

#include "vxWorks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "stdioLib.h"
#include "strLib.h"
#include "hostLib.h"
#include "ioLib.h"
#include "udpExample.h"

256
13 Writing Sample Applications Using Sockets
13.2 Writing Applications Using Datagram Sockets (UDP)

/****************************************************************************
*
* udpClient - send a message to a server over a UDP socket
*
* This routine sends a user-provided message to a server over a UDP socket.
* Optionally, this routine can request that the server display the message.
* This routine may be invoked as follows:
* -> udpClient "remoteSystem"
* Message to send:
* Greetings from UDP client
* Would you like server to display your message (Y or N):
* y
* value = 0 = 0x0
*
* RETURNS: OK, or ERROR if the message could not be sent to the server.
*/

STATUS udpClient
(
char * serverName /* name or IP address of server */
)
{
struct request myRequest; /* request to send to server */
struct sockaddr_in serverAddr; /* server's socket address */
char display; /* if TRUE, server prints message */
int sockAddrSize; /* size of socket address structure */ 13
int sFd; /* socket file descriptor */
int mlen; /* length of message */

/* create client's socket */

if ((sFd = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR)


{
perror ("socket");
return (ERROR);
}

/* bind not required - port number is dynamic */

/* build server socket address */

sockAddrSize = sizeof (struct sockaddr_in);


bzero ((char *) &serverAddr, sockAddrSize);
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons (SERVER_PORT_NUM);

if (((serverAddr.sin_addr.s_addr = inet_addr (serverName)) == ERROR) &&


((serverAddr.sin_addr.s_addr = hostGetByName (serverName)) == ERROR))
{
perror ("unknown server name");
close (sFd);
return (ERROR);
}

257
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* build request, prompting user for message */

printf ("Message to send: \n");


mlen = read (STD_IN, myRequest.message, REQUEST_MSG_SIZE);
myRequest.message[mlen - 1] = '\0';

printf ("Would you like the server to display your message (Y or N): \n");
read (STD_IN, &display, 1);
switch (display)
{
case 'y':
case 'Y': myRequest.display = TRUE;
break;
default: myRequest.display = FALSE;
break;
}

/* send request to server */

if (sendto (sFd, (caddr_t) &myRequest, sizeof (myRequest), 0,


(struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)
{
perror ("sendto");
close (sFd);
return (ERROR);
}

close (sFd);
return (OK);
}

/* udpServer.c - UDP server example */

/*
DESCRIPTION
This file contains the server-side of the VxWorks UDP example code.
The example code demonstrates the usage of several BSD 4.4-style
socket routine calls.
*/

/* includes */
#include "vxWorks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "stdioLib.h"
#include "strLib.h"
#include "ioLib.h"
#include "fioLib.h"
#include "udpExample.h"

/*********************************************************************
*
* udpServer - read from UDP socket and display client's message if requested
*
* Example UDP server:

258
13 Writing Sample Applications Using Sockets
13.2 Writing Applications Using Datagram Sockets (UDP)

* -> sp udpServer
* task spawned: id = 0x3a1f6c, name = t2
* value = 3809132 = 0x3a1f6c
* -> MESSAGE FROM CLIENT (Internet Address 192.0.2.11, port 1028):
* Greetings from UDP client
*
* RETURNS: Never, or ERROR if a resources could not be allocated.
*/

STATUS udpServer (void)


{
struct sockaddr_in serverAddr; /* server's socket address */
struct sockaddr_in clientAddr; /* client's socket address */
struct request clientRequest; /* request/Message from client */
int sockAddrSize; /* size of socket address structure */
int sFd; /* socket file descriptor */
char inetAddr[INET_ADDR_LEN];
/* buffer for client's inet addr */

/* set up the local address */

sockAddrSize = sizeof (struct sockaddr_in);


bzero ((char *) &serverAddr, sockAddrSize);
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons (SERVER_PORT_NUM); 13
serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);

/* create a UDP-based socket */

if ((sFd = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR)


{
perror ("socket");
return (ERROR);
}

/* bind socket to local address */

if (bind (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)


{
perror ("bind");
close (sFd);
return (ERROR);
}

/* read data from a socket and satisfy requests */

FOREVER
{
if (recvfrom (sFd, (char *) &clientRequest, sizeof (clientRequest), 0,
(struct sockaddr *) &clientAddr, &sockAddrSize) == ERROR)
{
perror ("recvfrom");
close (sFd);
return (ERROR);
}

259
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* if client requested that message be displayed, print it */

if (clientRequest.display)
{
/* convert inet address to dot notation */

inet_ntoa_b (clientAddr.sin_addr, inetAddr);


printf ("MSG FROM CLIENT (Internet Address %s, port %d):\n%s\n",
inetAddr, ntohs (clientAddr.sin_port), clientRequest.message);
}
}
}

13.2.2 Using a Datagram (UDP) Socket to Access IPv4 Multicasting

IP multicasting is the delivery of the same packets to multiple IP addresses. Typical


multicasting applications include audio and video conferencing, resource
discovery tools, and shared white boards. Multicasting is a feature of the IP layer,
but to access this routine, an application uses a UDP socket.
A task must multicast on a network interface driver that supports multicasting
(many do not). To review the capabilities of all attached network drivers, use
ifShow( ). If a network interface supports multicasting, IFF_MULTICAST is listed
among the flags for that network interface.
Multicast IPv4 addresses range from 224.0.0.0 to 239.255.255.255. These addresses
are also called class D addresses or multicast groups. A datagram with a class D
destination address is delivered to every process that has joined the corresponding
multicast group.
To multicast a packet, a task need do nothing special. The task just sends to the
appropriate multicast address. The process can use any normal UDP socket. To
update the route table to include the route to the destination multicast address, use
routec( ) or a routing socket connection.
To receive a multicast packet, a task must join a multicast group. To do this, the
task must use a setsockopt( ) call to set the appropriate socket options on the
socket (see Table 13-1).
When choosing an address upon which to multicast, remember that certain
addresses and address ranges are already registered to specific uses and protocols.
For example, 224.0.0.1 multicasts to all systems on the local subnet. The Internet
Assigned Numbers Authority (IANA) maintains a list of registered IP multicast
groups. For a list of the port assignments for well-known and registered services,
see:
http://www.iana.org/assignments/port-numbers

260
13 Writing Sample Applications Using Sockets
13.2 Writing Applications Using Datagram Sockets (UDP)

Table 13-1 IPv4 Multicasting Socket Options a

Command Argument Description

IP_MULTICAST_IF struct in_addr Select default interface for outgoing


multicasts.
IP_MULTICAST_TTL CHAR Select default time to live (TTL) for
outgoing multicast packets.
IP_MULTICAST_LOOP CHAR Enable or disable loopback of
outgoing multicasts.
IP_ADD_MEMBERSHIP struct ip_mreq Join a multicast group.
IP_DROP_MEMBERSHIP struct ip_mreq Leave a multicast group.
a. For more on IPv4 multicasting socket options, see the setsockopt( ) reference entry.
For information on IPv6 equivalents, see RFC 3493 and RFC 3542.

The following code samples define two routines, mcastSend( ) and mcastRcv( ).
13
These routines demonstrate how to use UDP sockets to handle sending and
receiving multicast traffic.
mcastSend( )
Transmits a buffer to the specified multicast address. As input, this routine
expects a multicast destination, a port number, a buffer pointer, and a buffer
length. For example:
status = mcastSend ("224.1.0.1", 7777, bufPtr, 100);

mcastRcv( )
Receives any packet sent to a specified multicast address. As input, this
routine expects the interface address from which the packet is coming, a
multicast address, a port number, and the number of bytes to read from the
packet. The returned value of the routine is a pointer a buffer containing the
read bytes. For example:
buf = mcastRcv (ifAddress, "224.1.0.1", 7777, 100) ;

Example 13-2 Datagram Sockets (UDP) and Multicasting

/* includes */
#include "vxWorks.h"
#include "taskLib.h"
#include "socket.h"
#include "netinet/in.h"
#include "stdio.h"

261
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

#include "stdlib.h"
#include "string.h"
#include "sockLib.h"
#include "inetLib.h"
#include "ioLib.h"
#include "routeLib.h"

/* defines */
/* globals */
/* forward declarations */

STATUS mcastSend (char * mcastAddr, USHORT mcastPort, char * sendBuf,


int sendLen);
char * mcastRcv (char * ifAddr, char * mcastAddr, USHORT mcastPort,
int numRead);

/************************************************************************
* mcastSend - send a message to the multicast address
* This routine sends a message to the multicast address
* The multicast group address to send, the port number, the pointer to the
* send buffer and the send buffer length are given as input parameters.
* RETURNS: OK if sucessful or ERROR
*/

STATUS mcastSend
(
char * mcastAddr, /* multicast address */
USHORT mcastPort, /* udp port number */
char * sendBuf, /* send Buffer */
int sendLen /* length of send buffer */
)
{
struct sockaddr_in sin;
struct sockaddr_in toAddr;
int toAddrLen;
int sockDesc;
char * bufPtr;
int len;
struct in_addr ifAddr;

/* create a send and recv socket */

if ((sockDesc = socket (AF_INET, SOCK_DGRAM, 0)) < 0 )


{
printf (" cannot open send socket\n");
return (ERROR);
}

ifAddr.s_addr = inet_addr (MCAST_INTERFACE);


if (setsockopt (sockDesc, IPPROTO_IP, IP_MULTICAST_IF, (char *)&ifAddr,
sizeof(struct in_addr)) < 0) {
printf ("setsockopt IP_MULTICAST_IF error:\n");
close (sockDesc);
return (ERROR);
} /* MCAST_INTERFACE indicates the interface's IPaddress */
/* which would be used to send multicast. */

262
13 Writing Sample Applications Using Sockets
13.2 Writing Applications Using Datagram Sockets (UDP)

/* zero out the structures */


bzero ((char *)&sin, sizeof (sin));
bzero ((char *)&toAddr, sizeof (toAddr));

sin.sin_len = (u_char) sizeof(sin);


sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(0);

if (bind(sockDesc, (struct sockaddr *)&sin, sizeof(sin)) != 0)


{
perror("bind");
if (sockDesc)
close (sockDesc);
return (ERROR);
}

toAddrLen = sizeof(struct sockaddr_in);


toAddr.sin_len = (u_char) toAddrLen;
toAddr.sin_family = AF_INET;

/* initialize the address to the send */


toAddr.sin_addr.s_addr = inet_addr (mcastAddr); 13

/* initialize the port to send */


toAddr.sin_port = htons(mcastPort);

bufPtr = sendBuf; /* initialize the buffer pointer */

/* send the buffer */


while (sendLen > 0)
{
if ((len = sendto (sockDesc, bufPtr, sendLen, 0,
(struct sockaddr *)&toAddr, toAddrLen)) < 0 )
{
printf("mcastSend sendto errno:0x%x\n", errno );
break;
}

sendLen -= len;
bufPtr += len;

taskDelay (1); /* give a taskDelay */


}

if (sockDesc != ERROR)
close (sockDesc);

return (OK);
}

263
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/************************************************************************
* mcastRcv - receive a message from a multicast address
* This routine receives a message from a multicast address
* The interface address from which to receive the multicast packet,
* the multicast address to recv from, the port number and the number of
* bytes to read are given as input parameters to this routine.
* RETURNS: Pointer to the Buffer or NULL if error.
*/

char * mcastRcv
(
char * ifAddr, /* interface address to recv mcast packets */
char * mcastAddr, /* multicast address */
USHORT mcastPort, /* udp port number to recv */
int numRead /* number of bytes to read */
)
{
struct sockaddr_in fromAddr;
struct sockaddr_in sin;
int fromLen;
struct ip_mreq ipMreq;
int recvLen;
int sockDesc;
char * bufPtr;
int status = OK;
char * recvBuf = NULL;

if ((sockDesc = socket (AF_INET, SOCK_DGRAM, 0)) < 0)


{
printf (" cannot open recv socket\n");
return (NULL);
}

bzero ((char *)&sin, sizeof (sin));


bzero ((char *) &fromAddr, sizeof(fromAddr));
fromLen = sizeof(fromAddr);

if ((recvBuf = calloc (numRead, sizeof (char))) == NULL)


{
printf (" calloc error, cannot allocate memory\n");
status = ERROR;
goto cleanUp;
}

sin.sin_len = (u_char) sizeof(sin);


sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;

/* UDP port number to match for the received packets */


sin.sin_port = htons (mcastPort);

/* bind a port number to the socket */


if (bind(sockDesc, (struct sockaddr *)&sin, sizeof(sin)) != 0)
{
perror("bind");
status = ERROR;

264
13 Writing Sample Applications Using Sockets
13.2 Writing Applications Using Datagram Sockets (UDP)

goto cleanUp;
}

/* fill in the argument structure to join the multicast group */


/* initialize the multicast address to join */

ipMreq.imr_multiaddr.s_addr = inet_addr (mcastAddr);

/* unicast interface addr from which to receive the multicast packets */


ipMreq.imr_interface.s_addr = inet_addr (ifAddr);

/* set the socket option to join the MULTICAST group */


if (setsockopt (sockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&ipMreq,
sizeof (ipMreq)) < 0)
{
printf ("setsockopt IP_ADD_MEMBERSHIP error:\n");
status = ERROR;
goto cleanUp;
}

/* get the data destined to the above multicast group */


bufPtr = recvBuf;

while (numRead > 0) 13


{
if ((recvLen = recvfrom (sockDesc, bufPtr, numRead, 0,
(struct sockaddr *)&fromAddr, &fromLen)) < 0)
{
perror("recvfrom");
status = ERROR;
break;
}
numRead -= recvLen; /* decrement number of bytes to read */
bufPtr += recvLen; /* increment the buffer pointer */
}

/* set the socket option to leave the MULTICAST group */


if (setsockopt (sockDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(char *)&ipMreq,
sizeof (ipMreq)) < 0)
printf ("setsockopt IP_DROP_MEMBERSHIP error:\n");

cleanUp:
{
if (sockDesc != ERROR)
close (sockDesc);
if ((status != OK) && (recvBuf != NULL))
{
free (recvBuf);
recvBuf = NULL;
}
}
return (recvBuf);
}

265
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

13.3 Writing Applications Using Stream Sockets (TCP)


The Transmission Control Protocol (TCP) provides reliable, two-way transmission
of data. In a TCP communication, two sockets are connected, allowing a reliable
byte-stream to flow between them in either direction. TCP is referred to as a virtual
circuit protocol, because it behaves as though a circuit is created between the two
sockets.
A good analogy for TCP communications is a telephone system. Connecting two
sockets is similar to calling from one telephone to another. After the connection is
established, you can write and read data (talk and listen).
Table 13-2 shows the steps in establishing socket communications with TCP, and
the analogy of each step with telephone communications.

Table 13-2 TCP Analogy to Telephone Communication

Task 1 Task 2
Waits Calls Routine Analogy

socket( ) socket( ) Create sockets. Hook up phones.

bind( ) Assign address to socket. Assign phone numbers.

listen( ) Allow others to connect to Allow others to call.


socket.

connect( ) Request connection to another Dial another phone’s


socket. number.

accept( ) Complete connection. Answer phone.

write( ) write( ) Send data to other socket. Talk.

read( ) read( ) Receive data from other socket. Listen.

close( ) close( ) Close sockets. Hang up.

Example 13-3 Stream Sockets (TCP)

The following code example uses a client-server communication model. The server
communicates with clients using stream-oriented (TCP) sockets. The main server
loop, in tcpServerWorkTask( ), reads requests, prints the client’s message to the
console, and, if requested, sends a reply back to the client. The client builds the
request by prompting for input. It sends a message to the server and, optionally,

266
13 Writing Sample Applications Using Sockets
13.3 Writing Applications Using Stream Sockets (TCP)

waits for a reply to be sent back. To simplify the example, assume that the code is
executed on machines that have the same data sizes and alignment.
/* tcpExample.h - header used by both TCP server and client examples */

/* defines */
#define SERVER_PORT_NUM 5001 /* server's port number for bind() */
#define SERVER_WORK_PRIORITY 100 /* priority of server's work task */
#define SERVER_STACK_SIZE 10000 /* stack size of server's work task */
#define SERVER_MAX_CONNECTIONS 4 /* max clients connected at a time */
#define REQUEST_MSG_SIZE 1024 /* max size of request message */
#define REPLY_MSG_SIZE 500 /* max size of reply message */

/* structure for requests from clients to server */


struct request
{
int reply; /* TRUE = request reply from server */
int msgLen; /* length of message text */
char message[REQUEST_MSG_SIZE]; /* message buffer */
};

/* tcpClient.c - TCP client example */

/*
DESCRIPTION 13
This file contains the client-side of the TCP example code.
The example code demonstrates the usage of several BSD 4.4-style
socket routine calls.
*/

/* includes */

#include "vxWorks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "stdioLib.h"
#include "strLib.h"
#include "hostLib.h"
#include "ioLib.h"
#include "tcpExample.h"

/****************************************************************************
*
* tcpClient - send requests to server over a TCP socket
*
* This routine connects over a TCP socket to a server, and sends a
* user-provided message to the server. Optionally, this routine
* waits for the server's reply message.
*
* This routine may be invoked as follows:
* -> tcpClient "remoteSystem"
* Message to send:
* Hello out there
* Would you like a reply (Y or N):
* y

267
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

* value = 0 = 0x0
* -> MESSAGE FROM SERVER:
* Server received your message
*
* RETURNS: OK, or ERROR if the message could not be sent to the server.
*/

STATUS tcpClient
(
char * serverName /* name or IP address of server */
)
{
struct request myRequest; /* request to send to server */
struct sockaddr_in serverAddr; /* server's socket address */
char replyBuf[REPLY_MSG_SIZE]; /* buffer for reply */
char reply; /* if TRUE, expect reply back */
int sockAddrSize; /* size of socket address structure */
int sFd; /* socket file descriptor */
int mlen; /* length of message */

/* create client's socket */


if ((sFd = socket (AF_INET, SOCK_STREAM, 0)) == ERROR)
{
perror ("socket");
return (ERROR);
}

/* bind not required - port number is dynamic */


/* build server socket address */
sockAddrSize = sizeof (struct sockaddr_in);
bzero ((char *) &serverAddr, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_port = htons (SERVER_PORT_NUM);

if (((serverAddr.sin_addr.s_addr = inet_addr (serverName)) == ERROR) &&


((serverAddr.sin_addr.s_addr = hostGetByName (serverName)) == ERROR))
{
perror ("unknown server name");
close (sFd);
return (ERROR);
}

/* connect to server */
if (connect (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)
{
perror ("connect");
close (sFd);
return (ERROR);
}

/* build request, prompting user for message */


printf ("Message to send: \n");
mlen = read (STD_IN, myRequest.message, REQUEST_MSG_SIZE);
myRequest.msgLen = mlen;
myRequest.message[mlen - 1] = '\0';

268
13 Writing Sample Applications Using Sockets
13.3 Writing Applications Using Stream Sockets (TCP)

printf ("Would you like a reply (Y or N): \n");


read (STD_IN, &reply, 1);
switch (reply)
{
case 'y':
case 'Y': myRequest.reply = TRUE;
break;
default: myRequest.reply = FALSE;
break;
}

/* send request to server */

if (write (sFd, (char *) &myRequest, sizeof (myRequest)) == ERROR)


{
perror ("write");
close (sFd);
return (ERROR);
}

if (myRequest.reply) /* if expecting reply, read and display it */


{
if (read (sFd, replyBuf, REPLY_MSG_SIZE) < 0)
{
perror ("read");
close (sFd); 13
return (ERROR);
}

printf ("MESSAGE FROM SERVER:\n%s\n", replyBuf);


}

close (sFd);
return (OK);
}

/* tcpServer.c - TCP server example */

/*
DESCRIPTION
This file contains the server-side of the TCP example code.
The example code demonstrates the usage of several BSD 4.4-style
socket routine calls.
*/

/* includes */
#include "vxWorks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "taskLib.h"
#include "stdioLib.h"
#include "strLib.h"
#include "ioLib.h"
#include "fioLib.h"
#include "tcpExample.h"

269
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* routine declarations */

VOID tcpServerWorkTask (int sFd, char * address, u_short port);

/****************************************************************************
*
* tcpServer - accept and process requests over a TCP socket
*
* This routine creates a TCP socket and accepts connections over the socket
* from clients. Each client connection is handled by spawning a separate
* task to handle client requests. This routine may be invoked as follows:
* -> sp tcpServer
* task spawned: id = 0x3a6f1c, name = t1
* value = 3829532 = 0x3a6f1c
* -> MESSAGE FROM CLIENT (Internet Address 192.0.2.10, port 1027):
* Hello out there
*
* RETURNS: Never, or ERROR if a resources could not be allocated.
*/

STATUS tcpServer (void)


{
struct sockaddr_in serverAddr; /* server's socket address */
struct sockaddr_in clientAddr; /* client's socket address */
int sockAddrSize; /* size of socket address structure */
int sFd; /* socket file descriptor */
int newFd; /* socket descriptor from accept */
int ix = 0; /* counter for work task names */
char workName[16]; /* name of work task */

/* set up the local address */

sockAddrSize = sizeof (struct sockaddr_in);


bzero ((char *) &serverAddr, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_port = htons (SERVER_PORT_NUM);
serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);

/* create a TCP-based socket */

if ((sFd = socket (AF_INET, SOCK_STREAM, 0)) == ERROR)


{
perror ("socket");
return (ERROR);
}

/* bind socket to local address */

if (bind (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)


{
perror ("bind");
close (sFd);
return (ERROR);
}

270
13 Writing Sample Applications Using Sockets
13.3 Writing Applications Using Stream Sockets (TCP)

/* create queue for client connection requests */

if (listen (sFd, SERVER_MAX_CONNECTIONS) == ERROR)


{
perror ("listen");
close (sFd);
return (ERROR);
}

/* accept new connect requests and spawn tasks to process them */

FOREVER
{
if ((newFd = accept (sFd, (struct sockaddr *) &clientAddr,
&sockAddrSize)) == ERROR)
{
perror ("accept");
close (sFd);
return (ERROR);
}

sprintf (workName, "tTcpWork%d", ix++);


if (taskSpawn(workName, SERVER_WORK_PRIORITY, 0, SERVER_STACK_SIZE,
(FUNCPTR) tcpServerWorkTask, newFd,
(int) inet_ntoa (clientAddr.sin_addr), ntohs (clientAddr.sin_port),
0, 0, 0, 0, 0, 0, 0) == ERROR) 13
{
/* if taskSpawn fails, close fd and return to top of loop */

perror ("taskSpawn");
close (newFd);
}
}
}

/****************************************************************************
*
* tcpServerWorkTask - process client requests
*
* This routine reads from the server's socket, and processes client
* requests. If the client requests a reply message, this routine
* will send a reply to the client.
*
* RETURNS: N/A.
*/

VOID tcpServerWorkTask
(
int sFd, /* server's socket fd */
char * address, /* client's socket address */
u_short port /* client's socket port */
)
{
struct request clientRequest; /* request/message from client */
int nRead; /* number of bytes read */
static char replyMsg[] = "Server received your message";

271
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* read client request, display message */

while ((nRead = fioRead (sFd, (char *) &clientRequest,


sizeof (clientRequest))) > 0)
{
printf ("MESSAGE FROM CLIENT (Internet Address %s, port %d):\n%s\n",
address, port, clientRequest.message);

free (address); /* free malloc from inet_ntoa() */

if (clientRequest.reply)
if (write (sFd, replyMsg, sizeof (replyMsg)) == ERROR)
perror ("write");
}

if (nRead == ERROR) /* error from read() */


perror ("read");

close (sFd); /* close server socket connection */


}

272
14
Using Fast UDP and
Zbuf Sockets

14.1 Introduction 273


14.2 Fast UDP 274
14.3 Zbuf Sockets 275

14.1 Introduction
This chapter describes two alternatives to using the standard socket interface:

Fast UDP

Fast UDP is a specialized library that provides faster throughput and less
complexity than the standard socket interface.
■ Zbuf Sockets

Zbuf sockets are an alternative set of socket calls based on a data abstraction
called a zbuf, a zero-copy buffer. Zbuf sockets can be used with either UDP or
TCP applications.

273
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

14.2 Fast UDP


The Wind River Fast UDP implementation is an API that you can use to send and
receive data over UDPv4 or UDPv6 with substantially higher throughput than is
achievable using the socket library. Compared to a socket interface, this specialized
library offers a limited feature set, but the primary goal of this library is to provide
faster data exchange while avoiding the complexity of the standard socket
interface.

Configuring VxWorks for Fast UDP

The Wind River Network Stack supports the following Fast UDP configuration
components:

Fast UDPv4

Fast UDPv6
These components are listed under the
Network Components > Network Private Components folder in Workbench.
To add Fast UDP support, you must first rebuild the stack libraries with
-DFASTUDP option set. These libraries are not built for the default stack. For
information on building the network stack, see your Wind River Platforms Getting
Started or Wind River General Purpose Platform, VxWorks Edition, Getting Started.
Once you have rebuilt the stack, you must then add the appropriate Fast UDP
component to your VxWorks image.

Fast UDPv4

The INCLUDE_FASTUDP component pulls in fastUdpLib, a library that


implements an API that you can use to send and receive data over UDPv4 with
substantially higher throughput than is achievable using the socket library.
Compared to a socket interface, this specialized library offers a limited feature set,
but the primary goal of this library is to provide faster data exchange while
avoiding the complexity of the standard socket interface. For information on how
to use the fastUdpLib API, see the fastUdpLib reference entries.
This component requires the following configuration components:

INCLUDE_IPV4

INCLUDE_ZBUF_SOCK

INCLUDE_NET_FUNCBIND

274
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

This component supports the following configuration parameter:

FASTUDP_DEBUG_CFG

Synopsis: Fast UDP debugging. 0 disables debugging. 1 enables it.


Default: 0

Fast UDPv6

The INCLUDE_FASTUDP6 component pulls in fastUdp6Lib, a library that


implements an API that you can use to send and receive data over UDPv6 with
substantially higher throughput than is achievable using the socket library.
Compared to a socket interface, this specialized library offers a limited feature set,
but the primary goal of this library is to provide faster data exchange while
avoiding the complexity of the standard socket interface. For information on how
to use the fastUdp6Lib API, see the fastUdp6Lib reference entries.
This component requires the following configuration components:
■ INCLUDE_IPV6
■ INCLUDE_ZBUF_SOCK
14
■ INCLUDE_NET_FUNCBIND

This component supports the following configuration parameter:

FASTUDP6_DEBUG_CFG

Synopsis: FastUDPv6 debugging. 0 disables debugging. 1 enables it.


Default: 0

14.3 Zbuf Sockets


Using the zbuf socket interface, applications can read and write UNIX BSD sockets
without copying data between application buffers and network buffers. You can
use zbufs with either UDP or TCP applications. The TCP subset of the zbuf
interface is sometimes called zero-copy TCP.

NOTE: Zbuf Sockets are a kernel-only feature. They are not supported in an RTP.

275
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Zbuf-based socket calls are interoperable with the standard BSD socket interface:
the other end of a socket has no way of telling whether your end is using
zbuf-based calls or traditional calls. However, zbuf-based socket calls are not
source-compatible with the standard BSD socket interface: you must call different
socket routines to use the zbuf interface. Applications that use the zbuf interface
are thus less portable.

! WARNING: The send socket buffer size must exceed that of any zbufs sent over the
socket. To set the send socket buffer size, use either the TCP_SND_SIZE_DFLT or
UDP_SND_SIZE_DFLT configuration parameter.

Configuring VxWorks for Zbuf Sockets

The Wind River Network Stack supports the following zbuf socket configuration
component:

ZBUF Socket
This component is listed under the
Network Components > Network Socket Components folder in Workbench.

ZBUF Socket

The INCLUDE_ZBUF_SOCK component pulls in zbufLib and zbufSockLib. The


zbufLib library provides a buffer management API for a data abstraction called a
zbuf, a zero-copy buffer. The zbufSockLib library provides an alternative set of
socket calls that use the zbuf.
Using the zbuf socket interface, applications can read and write UNIX BSD sockets
without copying data between application buffers and network buffers.
The INCLUDE_ZBUF_SOCK component has no component dependencies or
configuration parameters.

NOTE: Zbuf sockets are a kernel-only feature. They are not supported in RTPs.

276
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

14.3.1 Using Zbuf Calls to Send Existing Data Buffers

The simplest way to use zbuf sockets is to call either zbufSockBufSend( ) (in place
of send( ) for a TCP connection) or zbufSockBufSendto( ) (in place of sendto( ) for
a UDP datagram). In either case, you supply a pointer to your application’s data
buffer containing the data or message to send, and the network protocol uses that
same buffer rather than copying the data out of it.

! WARNING: Using zbufs allows different modules to share the same buffers. This
lets your application avoid the performance hit associated with copying the buffer.
To make this work, your application must not modify (let alone free!) the data
buffer while network software is still using it. Instead of freeing your buffer
explicitly, you can supply a free-routine callback: a pointer to a routine that knows
how to free the buffer. The zbuf library keeps track of how many zbufs point to a
data buffer and calls the free routine when the data buffer is no longer in use.

To receive socket data using zbufs, see the following sections. 14.3.2 Manipulating
the Zbuf Data Structure, p.277 describes the routines to create and manage zbufs,
and 14.3.7 Calling Zbuf Socket Routines, p.286, introduces the remaining
zbuf-specific socket routines. See also the reference entries for zbufLib and
zbufSockLib. 14

14.3.2 Manipulating the Zbuf Data Structure

A zbuf has three essential properties:



A zbuf holds a sequence of bytes.

The data in a zbuf is organized into one or more segments of contiguous data.
Successive zbuf segments are not usually contiguous to each other.

Zbuf segments refer to data buffers through pointers. The underlying data
buffers can be shared by more than one zbuf segment.
Zbuf segments are at the heart of how zbufs minimize data copying; if you have a
data buffer, you can incorporate it (by reference, so that only pointers and lengths
move around) into a new zbuf segment. Conversely, you can get pointers to the
data in zbuf segments, and examine the data there directly.

277
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Zbuf Byte Locations

You can address the contents of a zbuf by byte locations. A zbuf byte location has
two parts, an offset and a segment ID.
An offset is a signed integer (type int): the distance in bytes to a portion of data in
the zbuf, relative to the beginning of a particular segment. Zero refers to the first
byte in a segment; negative integers refer to bytes in previous segments; and
positive integers refer to bytes after the start of the current segment.
A segment ID is an arbitrary integer (type ZBUF_SEG) that identifies a particular
segment of a zbuf. You can always use NULL to refer to the first segment of a zbuf.
Figure 14-1 shows a simple zbuf with data organized into two segments. The
offsets are relative to the first segment. This is the most efficient addressing scheme
to use to refer to bytes a, b, or c in the figure.

Figure 14-1 Zbuf Addressing Relative to First Segment (NULL)

a b c

0 1 2

d e f g
3 4 5 6

Figure 14-2 shows the same zbuf, but it is labeled with offsets relative to the second
segment. This is the most efficient addressing scheme to refer to bytes d, e, f, or g
in the figure.

Figure 14-2 Zbuf Addressing Relative to Second Segment

–3 –2 –1

a b c

0 1 2 3

d e f g

278
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

Two special shortcuts give the fastest access to either the beginning or the end of a
zbuf. The constant ZBUF_END refers to the position after all existing bytes in the
zbuf. Similarly, ZBUF_BEGIN refers to the position before all existing bytes. These
constants are the only offsets with meanings not relative to a particular segment.
When you insert data in a zbuf, the new data is always inserted before the byte
location you specify in the call to an insertion routine. That is, the byte location you
specify becomes the address of the newly inserted data.

Creating and Destroying Zbufs

To create a new zbuf, call zbufCreate( ). The routine takes no arguments, and
returns a zbuf identifier (type ZBUF_ID) for a zbuf containing no segments. After
you have the zbuf ID, you can attach segments or otherwise insert data. While the
zbuf is empty, NULL is the only valid segment ID, and 0 the only valid offset.
When you no longer need a particular zbuf, call zbufDelete( ). Its single argument
is the ID for the zbuf to delete. The zbufDelete( ) routine calls the free routine
associated with each segment in the zbuf, for segments that are not shared by other
zbufs. After you delete a zbuf, its zbuf ID is meaningless; any reference to a deleted
zbuf ID is an error. 14

Table 14-1 Zbuf Creation and Deletion Routines

Call Description

zbufCreate( ) Create an empty zbuf.

zbufDelete( ) Delete a zbuf and free any associated segments.

Getting Data In and Out of Zbufs

The usual way to place data in a zbuf is to call zbufInsertBuf( ). This routine builds
a zbuf segment pointing to an existing data buffer, and inserts the new segment at
whatever byte location you specify in a zbuf. You can also supply a callback
pointer to a free routine, which the zbuf library calls when no zbuf segments point
to that data buffer.
Because the purpose of the zbuf socket interface is to avoid data copying, the need
to actually copy data into a zbuf (rather than designating its location as a shareable
buffer) occurs much less frequently. When that need does arise, the routine

279
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

zbufInsertCopy( ) is available. This routine does not require a callback pointer to


a free routine, because the original source of the data is not shared.
Similarly, the most efficient way to examine data in zbufs is to read it in place,
rather than to copy it to another location. If you must copy some of the data out of
a zbuf (for example, to guarantee the data is contiguous, or to place it in a data
structure required by another interface), call zbufExtractCopy( ). Within the call,
specify what to copy (zbuf ID, byte location, and the number of bytes) and where
to put it (an application buffer).

Table 14-2 Zbuf Data Copying Routines

Call Description

zbufInsertBuf( ) Create a zbuf segment from a buffer and insert into a zbuf.

zbufInsertCopy( ) Copy buffer data into a zbuf.

zbufExtractCopy( ) Copy data from a zbuf to a buffer.

14.3.3 Operations on Zbufs

The routines listed in Table 14-3 perform several fundamental operations on zbufs.

Table 14-3 Zbuf Operations

Call Description

zbufLength( ) Determine the length of a zbuf, in bytes.

zbufDup( ) Duplicate a zbuf.

zbufInsert( ) Insert a zbuf into another zbuf.

zbufSplit( ) Split a zbuf into two separate zbufs.

zbufCut( ) Delete bytes from a zbuf.

The routine zbufLength( ) reports how many bytes are in a zbuf.


The routine zbufDup( ) provides the simplest mechanism for sharing segments
between zbufs: it produces a new zbuf ID that refers to some or all of the data in
the original zbuf. You can exploit this sort of sharing to get two different views of
the same data. For example, after duplicating a zbuf, you can insert another zbuf
into one of the two duplicates, with zbufInsert( ). None of the data in the original

280
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

zbuf segments moves, yet after some byte location (the byte location where you
inserted data) addressing the two zbufs gives completely different data.
The zbufSplit( ) routine divides one zbuf into two; you specify the byte location
for the split, and the result of the routine is a new zbuf ID. The new zbuf’s data
begins after the specified byte location. The original zbuf ID also has a modified
view of the data: it is truncated to the byte location of the split. None of the data in
the underlying segments moves through all this. If you duplicate the original zbuf
before splitting it, three zbuf IDs share segments. The duplicate permits you to
view the entire original range of data, another zbuf contains a leading fragment,
and the third zbuf holds the trailing fragment.
Similarly, if you call zbufCut( ) to remove some range of bytes from within a zbuf,
the effects are visible only to callers who view the data through the same zbuf ID
you used for the deletion. Other zbuf segments can still address the original data
through a shared buffer.
For the most part, these routines do not free data buffers or delete zbufs, but there
are two exceptions:
■ zbufInsert( ) deletes the zbuf ID it inserts. No segments are freed, because they
now form part of the larger zbuf.
14
■ If the bytes you remove with zbufCut( ) span one or more complete segments,
the free routines for those segments can be called (if no other zbuf segment
refers to the same data).
The data-buffer free routine runs only when none of the data in a segment is part
of any zbuf. To avoid data copying, zbuf manipulation routines, such as
zbufCut( ), record which parts of a segment are currently in a zbuf, postponing the
deletion of a segment until no part of its data is in use.

14.3.4 Segments of Zbufs

The routines in Table 14-4 give your applications access to the underlying
segments in a zbuf.
By specifying a NULL segment ID, you can address the entire contents of a zbuf as
offsets from its very first data byte. It is always more efficient to address data in a
zbuf relative to the closest segment. Use zbufSegFind( ) to translate any zbuf byte
location into the most local form.
The pair zbufSegNext( ) and zbufSegPrev( ) are useful for going through the
segments of a zbuf in order, perhaps in conjunction with zbufSegLength( ).

281
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 14-4 Zbuf Segment Routines

Call Description

zbufSegFind( ) Find the zbuf segment containing a specified byte location.

zbufSegNext( ) Get the next segment in a zbuf.

zbufSegPrev( ) Get the previous segment in a zbuf.

zbufSegData( ) Determine the location of data in a zbuf segment.

zbufSegLength( ) Determine the length of a zbuf segment.

Finally, zbufSegData( ) allows the most direct access to the data in zbufs: it gives
your application the address where a segment’s data begins. If you manage
segment data directly using this pointer, bear the following restrictions in mind:
■ Do not change data if any other zbuf segment is sharing it.
■ As with any other direct memory access, it is up to your own code to restrict
itself to meaningful data: remember that the next segment in a zbuf is usually
not contiguous. Use zbufSegLength( ) as a limit, and zbufSegNext( ) when
you exceed that limit.

14.3.5 Manipulating the Zbuf Structure

The following interaction illustrates the use of some of the previously described
zbufLib routines, and their effect on zbuf segments and data sharing. To keep the
example manageable, the zbuf data used is artificially small, and the execution
environment is a shell.
To begin, create a zbuf, and use its ID zId to verify that a newly created zbuf
contains no data; zbufLength( ) returns a result of 0.
-> zId = zbufCreate()
new symbol "zId" added to symbol table.
zId = 0x3b58e8: value = 3886816 = 0x3b4ee0
-> zbufLength (zId)
value = 0 = 0x0

Next, create a data buffer buf1, insert it into zbuf zId, and verify that
zbufLength( ) now reports a positive length.

282
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

To keep the example simple, buf1 is a literal string, and therefore we do not supply
a free-routine callback argument to zbufInsertBuf( ).
-> buf1 = "I cannot repeat enough!"
new symbol "buf1" added to symbol table.
buf1 = 0x3b5898: value = 3889320 = 0x3b58a8 = buf1 + 0x10
-> zbufInsertBuf (zId, 0, 0, buf1, strlen(buf1), 0, 0)
value = 3850240 = 0x3ac000
-> zbufLength (zId)
value = 23 = 0x17

To examine the effect of other zbuf operations, it is useful to have a zbuf-display


routine. The remainder of this example uses a routine called zbufDisplay( ) for
that purpose; for the complete source code, see Example 14-1.
For each zbuf segment, zbufDisplay( ) shows the segment ID, the start-of-data
address, the offset from that address, the length of the segment, and the data in the
segment as a character string. The following display of zId illustrates that the
underlying data in its only segment is still at the buf1 address (0x3b58a8), because
zbufInsertBuf( ) incorporates its buffer argument into the zbuf without copying
data.
-> ld </usr/jane/zbuf-examples/zbufDisplay.o
value = 3890416 = 0x3b5cf0 = zbufDisplay.o_bss + 0x8
-> zbufDisplay zId 14
segID 0x3ac000 at 0x3b58a8 + 0x0 (23 bytes): I cannot repeat enough!
value = 0 = 0x0

When we copy the zbuf, the copy has its own IDs, but still uses the same data
address:
-> zId2 = zbufDup (zId,0,0,23)
new symbol "zId2" added to symbol table.
zId2 = 0x3b5ff0: value = 3886824 = 0x3b4ee8
-> zbufDisplay zId2
segID 0x3abf80 at 0x3b58a8 + 0x0 (23 bytes): I cannot repeat enough!
value = 0 = 0x0

If we insert a second buffer into the middle of the existing data in zId, there is still
no data copying. Inserting the new buffer gives us a zbuf made up of three
segments—but notice that the address of the first segment is still the start of buf1,
and the third segment points into the middle of buf1:
-> buf2 = " this"
new symbol "buf2" added to symbol table.
buf2 = 0x3b5fb0: value = 3891136 = 0x3b5fc0 = buf2 + 0x10
-> zbufInsertBuf (zId, 0, 15, buf2, strlen(buf2), 0, 0)
value = 3849984 = 0x3abf00
-> zbufDisplay zId
segID 0x3ac000 at 0x3b58a8 + 0x0 (15 bytes): I cannot repeat
segID 0x3abf00 at 0x3b5fc0 + 0x0 ( 5 bytes): this
segID 0x3abe80 at 0x3b58b7 + 0x0 ( 8 bytes): enough!
value = 0 = 0x0

283
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Because the underlying buffer is not modified, both buf1 and the duplicate zbuf
zId2 still contain the original string, rather than the modified one now in zId:
-> printf ("%s\n", buf1)
I cannot repeat enough!
value = 24 = 0x18
-> zbufDisplay zId2
segID 0x3abf80 at 0x3b58a8 + 0x0 (23 bytes): I cannot repeat enough!
value = 0 = 0x0

The zbufDup( ) routine can also select part of a zbuf without copying, for instance
to incorporate some of the same data into another zbuf—or even into the same
zbuf, as in the following example:
-> zTmp = zbufDup (zId, 0, 15, 5)
new symbol "zTmp" added to symbol table.
zTmp = 0x3b5f70: value = 3886832 = 0x3b4ef0

-> zbufInsert (zId, 0, 15, zTmp)


value = 3849728 = 0x3abe00
-> zbufDisplay zId
segID 0x3ac000 at 0x3b58a8 + 0x0 (15 bytes): I cannot repeat
segID 0x3abe00 at 0x3b5fc0 + 0x0 ( 5 bytes): this
segID 0x3abf00 at 0x3b5fc0 + 0x0 ( 5 bytes): this
segID 0x3abe80 at 0x3b58b7 + 0x0 ( 8 bytes): enough!
value = 0 = 0x0

After zbufInsert( ) combines two zbufs, the second zbuf ID (zTmp in this example)
is automatically deleted. Thus, zTmp is no longer a valid zbuf ID—for example,
zbufLength( ) returns ERROR:
-> zbufLength (zTmp)
value = -1 = 0xffffffff = zId2 + 0xffc4a00f

You must still delete the remaining two zbuf IDs explicitly when they are no longer
needed. This releases all associated zbuf-structure storage. In a real application,
with free-routine callbacks filled in, it also calls the specified free routine on the
data buffers, as follows:
-> zbufDelete (zId)
value = 0 = 0x0
-> zbufDelete (zId2)
value = 0 = 0x0

284
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

Example 14-1 Zbuf Display Routine

The following is the complete source code for the zbufDisplay( ) utility used in the
preceding example:
/* zbufDisplay.c - zbuf example display routine */

/* includes */

#include "vxWorks.h"
#include "zbufLib.h"
#include "ioLib.h"
#include "stdio.h"
/********************************************************************
*
* zbufDisplay - display contents of a zbuf
*
* RETURNS: OK, or ERROR if the specified data could not be displayed.
*/
STATUS zbufDisplay
(
ZBUF_ID zbufId, /* zbuf to display */
ZBUF_SEG zbufSeg, /* zbuf segment base for <offset> */
int offset, /* relative byte offset */
int len, /* number of bytes to display */
BOOL silent /* do not print out debug info */
) 14
{
int lenData;
char * pData;
/* find the most-local byte location */
if ((zbufSeg = zbufSegFind (zbufId, zbufSeg, &offset)) == NULL)
return (ERROR);
if (len <= 0)
len = ZBUF_END;
while ((len != 0) && (zbufSeg != NULL))
{
/* find location and data length of zbuf segment */
pData = zbufSegData (zbufId, zbufSeg) + offset;
lenData = zbufSegLength (zbufId, zbufSeg) - offset;
lenData = min (len, lenData); /* print all of seg ? */
if (!silent)
printf ("segID 0x%x at 0x%x + 0x%x (%2d bytes): ",
(int) zbufSeg, (int) pData, offset, lenData);
write (STD_OUT, pData, lenData); /* display data */
if (!silent)
printf ("\n");
zbufSeg = zbufSegNext (zbufId, zbufSeg); /* update segment */
len -= lenData; /* update length */
offset = 0; /* no more offset */
}
return (OK);
}

285
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

14.3.6 Limitations of the Zbuf Implementation

The following zbuf limitations are due to the current implementation; they are not
inherent to the data abstraction. They are described because they can have an
impact on application performance.

With the current implementation, references to data in zbuf segments before a
particular location (whether with zbufSegPrev( ), or with a negative offset in
a byte location) are significantly slower than references to data after a
particular location.
■ The data in small zbuf segments (less than 512 bytes) is sometimes copied,
rather than having references propagated to it.

14.3.7 Calling Zbuf Socket Routines

The zbuf socket calls listed in Table 14-5 are named to emphasize parallels with the
standard BSD socket calls: thus, zbufSockSend( ) is the zbuf version of send( ),
and zbufSockRecvfrom( ) is the zbuf version of recvfrom( ). The arguments also
correspond directly to those of the standard socket calls.

Table 14-5 Zbuf Socket Library Routines

Call Description

zbufSockLibInit( ) Initialize the socket libraries (called automatically if the


configuration has zbuf sockets enabled. The relevant
configuration parameter is INCLUDE_ZBUF_SOCK).

zbufSockSend( ) Send zbuf data through a TCP socket.

zbufSockSendto( ) Send a zbuf message through a UDP socket.

zbufSockBufSend( ) Create a zbuf and send it as TCP socket data.

zbufSockBufSendto( ) Create a zbuf and send it as a UDP socket message.

zbufSockRecv( ) Receive data in a zbuf from a TCP socket.

zbufSockRecvfrom( ) Receive a message in a zbuf from a UDP socket.

For a detailed description of each routine, see the corresponding reference entry.

286
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

Standard Socket Calls and Zbuf Socket Calls

The zbuf socket calls are particularly useful when large data transfer is a
significant part of your socket application. For example, many socket applications
contain sections of code like the following fragment:
pBuffer = malloc (BUFLEN);
while ((readLen = read (fdDevice, pBuffer, BUFLEN)) > 0)
write (fdSock, pBuffer, readLen);

You can eliminate the overhead of copying from the application buffer pBuffer
into the internal socket buffers by changing the code to use zbuf socket calls. For
example, the following fragment is a zbuf version of the preceding loop:
pBuffer = malloc (BUFLEN * BUFNUM); /* allocate memory */
for (ix = 0; ix < (BUFNUM - 1); ix++, pBuffer += BUFLEN)
appBufRetn (pBuffer); /* fill list of free bufs */

while ((readLen = read (fdDevice, pBuffer, BUFLEN)) > 0)


{
zId = zbufCreate (); /* insert into new zbuf */
zbufInsertBuf (zId, NULL, 0, pBuffer, readLen, appBufRetn, 0);
zbufSockSend (fdSock, zId, readLen, 0); /* send zbuf */
pBuffer = appBufGet (WAIT_FOREVER); /* get a fresh buffer */
}
14
The appBufGet( ) and appBufRetn( ) references in the preceding code fragment
stand for application-specific buffer management routines, analogous to malloc( )
and free( ). In many applications, these routines do nothing more than manipulate
a linked list of free fixed-length buffers.

TCP Example Server Using Zbufs

For a small but complete example that illustrates the mechanics of using the zbuf
socket library, consider the conversion of the client-server example in
Example 13-3 to use zbuf socket calls.
No conversion is needed for the client side of the example; the client operates the
same regardless of whether or not the server uses zbufs. The next example
illustrates the following changes to convert the server side to use zbufs:

Instead of including the header file sockLib.h, include zbufSockLib.h.

The data processing component must be capable of dealing with potentially
non-contiguous data in successive zbuf segments. In the TCP example, this
component displays a message using printf( ); we can use the zbufDisplay( )
routine from Example 14-1 instead.

287
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


The original TCP example exploits fioRead( ) to collect the complete message,
rather than calling recv( ) directly. To achieve the same end while avoiding
data copying by using zbufs, the following example defines a
zbufFioSockRecv( ) routine to call zbufSockRecv( ) repeatedly until the
complete message is received.

A new version of the worker routine tcpServerWorkTask( ) must tie together
these separate modifications, and must explicitly extract the reply and
msgLen fields from the client’s transmission to do so. When using zbufs, you
cannot extract these fields by reference to the C structure in tcpExample.h.
This is because of the possibility that the data is not contiguous.

Example 14-2 The TCP Example Server Using Zbufs

The following example shows the auxiliary zbufFioSockRecv( ) routine and the
zbuf version of tcpServerWorkTask( ). To run this code:
1. Start with tcpServer.c as defined in Example 13-3.
2. Include the header file zbufSockLib.h.
3. Insert the zbufDisplay( ) routine from Example 14-1.
4. Replace the tcpServerWorkTask( ) definition with the following two routines:
/************************************************************************
*
* zbufFioSockRecv - receive <len> bytes from a socket into a zbuf
*
* This routine receives a specified amount of data from a socket into a
* zbuf, by repeatedly calling zbufSockRecv() until <len> bytes are read.
*
* RETURNS:
* The ID of the zbuf containing <len> bytes of data,
* or NULL if there is an error during the zbufSockRecv() operation.
*
* SEE ALSO: zbufSockRecv()
*/
ZBUF_ID zbufFioSockRecv
(
int fd, /* file descriptor of file to read */
int len /* maximum number of bytes to read */
)
{
BOOL first = TRUE; /* first time thru ? */
ZBUF_ID zRecvTotal = NULL; /* zbuf to return */
ZBUF_ID zRecv; /* zbuf read from sock */
int nbytes; /* number of recv bytes */
for (; len > 0; len -= nbytes)
{
nbytes = len; /* set number of bytes wanted */
/* read a zbuf from the socket */

288
14 Using Fast UDP and Zbuf Sockets
14.3 Zbuf Sockets

if (((zRecv = zbufSockRecv (fd, 0, &nbytes)) == NULL) ||


(nbytes <= 0))
{
if (zRecvTotal != NULL)
zbufDelete (zRecvTotal);
return (NULL);
}
/* append recv'ed zbuf onto end of zRecvTotal */
if (first)
{
zRecvTotal = zRecv; /* cannot append to empty zbuf */
first = FALSE; /* can append now... */
}
else if (zbufInsert (zRecvTotal, NULL, ZBUF_END, zRecv) == NULL)
{
zbufDelete (zRecv);
zbufDelete (zRecvTotal);
return (NULL);
}
}
return (zRecvTotal);
}
/************************************************************************
*
* tcpServerWorkTask - process client requests
*
* This routine reads from the server's socket, and processes client
* requests. If the client requests a reply message, this routine 14
* sends a reply to the client.
*
* RETURNS: N/A.
*/

VOID tcpServerWorkTask
(
int sFd, /* server's socket fd */
char * address, /* client's socket address */
u_short port /* client's socket port */
)
{
static char replyMsg[] = "Server received your message";
ZBUF_ID zReplyOrig; /* original reply msg */
ZBUF_ID zReplyDup; /* duplicate reply msg */
ZBUF_ID zRequest; /* request msg from client */
int msgLen; /* request msg length */
int reply; /* reply requested ? */

/* create original reply message zbuf */

if ((zReplyOrig = zbufCreate ()) == NULL)


{
perror ("zbuf create");
free (address); /* free malloc from inet_ntoa() */
return;
}

289
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* insert reply message into zbuf */

if (zbufInsertBuf (zReplyOrig, NULL, 0, replyMsg,


sizeof (replyMsg), NULL, 0) == NULL)
{
perror ("zbuf insert");
zbufDelete (zReplyOrig);
free (address); /* free malloc from inet_ntoa() */
return;
}

/* read client request, display message */

while ((zRequest = zbufFioSockRecv (sFd, sizeof(struct request))) != NULL)


{
/* extract reply field into <reply> */
(void) zbufExtractCopy (zRequest, NULL, 0,
(char *) &reply, sizeof (reply));
(void) zbufCut (zRequest, NULL, 0, sizeof (reply));
/* extract msgLen field into <msgLen> */
(void) zbufExtractCopy (zRequest, NULL, 0,
(char *) &msgLen, sizeof (msgLen));
(void) zbufCut (zRequest, NULL, 0, sizeof (msgLen));
/* duplicate reply message zbuf, preserving original */
if ((zReplyDup = zbufDup (zReplyOrig, NULL, 0, ZBUF_END)) == NULL)
{
perror ("zbuf duplicate");
zbufDelete (zRequest);
break;
}
printf ("MESSAGE FROM CLIENT (Internet Address %s, port %d):\n",
address, port);

/* display request message zbuf */


(void) zbufDisplay (zRequest, NULL, 0, msgLen, TRUE);
printf ("\n");
if (reply)
{
if (zbufSockSend (sFd, zReplyDup, sizeof (replyMsg), 0) < 0)
perror ("zbufSockSend");
}
/* finished with request message zbuf */
zbufDelete (zRequest);
}
free (address); /* free malloc from inet_ntoa() */
zbufDelete (zReplyOrig);
close (sFd);
}

! CAUTION: In the interests of brevity, the STATUS return values for several zbuf
socket calls are discarded with casts to void. In a real application, check these
return values for possible errors.

290
15
Working with Routing Sockets

15.1 Introduction 291


15.2 Getting Started with Routing Sockets 293
15.3 Preparing and Processing Routing Socket Messages 295
15.4 Extracting Information from a Routing Socket Message 310
15.5 Building a Routing Socket Message 314

15.1 Introduction
Routing sockets provide a two-way communication interface to the route table.
Using a routing socket, an application can monitor and make changes to the
contents of the routing table.
Traditionally, a route table stored only one entry per destination network. For
IPv4, a destination network is identified by an IPv4 address and a netmask value.
For IPv6, a destination network is identified by an IPv6 address and a prefix value.
A route table entry associates this destination with a gateway on a local network
or with an interface on a local network. In previous route table implementations,
adding a route entry to the table failed if the table already contained an entry for
that destination.
Under the current network stack, the route table has been enhanced to store
multiple same-destination routes that differ by gateway value, TOS value, or

291
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

protocol value. Thus, in the current route table, adding a route entry to a table that
already contains an entry for that destination can succeed provided the new entry
differs from the existing entry (or entries) in its gateway value, TOS value, or
protocol value.

NOTE: Multi-route support is the default behavior. If you have access to the route
table source code, you can rebuild the code to exclude multi-route support. For
more information, see the Getting Started guide for your Platform.

When IP queries the route table, it expects to get back only one route. To satisfy this
expectation, the route table ranks multiple same-destination routes. The highest
ranked route, known as the primary or representative route for the destination, is
the route reported to IP. How the system ranks same-destination routes depends
on how you build the code.
This ability to store multiple same-destination routes is also not anticipated by the
standard routing socket message set. Thus, the standard routing socket message
set does not include messages that allow you to detect the reappearance of
secondary routes or to manipulate secondary routes. For this reason, the
Wind River Network Stack supports an enhanced message set. One of these new
message types, RTM_NEWIPROUTE, is available in all network stack versions.
In addition, the -DROUTER_STACK set of routing socket message types is
extended to facilitate cooperation among protocols that might need to share the
route table that stores redundant entries. For information on building the network
stack, see the Getting Started guide for your Platform.

Ranking Routes in the Host Stack Route Table

In the route table produced by a host stack build, multiple same-destination routes
are ranked by age. The oldest route is the primary route. All newer routes are
ranked below the primary route according to age. Deleting the current primary
route reveals the next oldest route, if any. Thus, the routes are ranked in FIFO
order.

Ranking Routes in the Router Stack Route Table

As mentioned above, the route table for a host build of the network stack ranks
multiple same-destination routes by age. However, if you build the network stack
with the -DROUTER_STACK option, multiple same-destination routes are ranked
by a user-assigned weight. If there are multiple same-destination routes, the
lowest weight entry is used as the representative route. If this representative route
is deleted, the next lowest-weight route becomes the new representative route.

292
15 Working with Routing Sockets
15.2 Getting Started with Routing Sockets

Location of route.h and if.h

This chapter makes frequent reference to the route.h and if.h files. The full
pathnames for these files are:
installDir/vxworks-6.n/target/h/wrn/coreip/net/if.h
installDir/vxworks-6.n/target/h/wrn/coreip/net/route.h

15.2 Getting Started with Routing Sockets


This section describes how to add routing socket support to VxWorks and how to
set up a routing socket.

15.2.1 Configuring VxWorks for Routing Sockets

The Wind River Network Stack supports the following routing socket
configuration component:

Routing Socket 15

This component is listed under the


Network Components > Network Socket Components folder in Workbench.
The INCLUDE_ROUTING_SOCKET component pulls in the routing socket
interface. Routing sockets provide a two-way communication interface to the route
table. Using a routing socket, an application can monitor as well as make changes
to the contents of the routing table.
There are no configuration parameters or externally callable functions directly
associated with this component.

15.2.2 Setting up a Routing Socket

Setting up a routing socket requires a socket( ) call. There is no need to make an


explicit bind( ) or connect( ) call for a routing socket. After creating a routing
socket, you may want to configure the socket options.

293
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Creating a Routing Socket

To create a socket descriptor for use as a socket in the routing domain, call socket( )
with a domain value of AF_ROUTE, a type value of SOCK_RAW, and a protocol value
of 0 (zero). For example:
myRouteSocket = socket (AF_ROUTE, SOCK_RAW, 0);
if (routeSocket < 0)
{
your response code for the socket call failure
}

Setting Socket Options on a Routing Socket

After you have the socket descriptor, you can make it non-blocking by making an
FIONBIO call to ioctl( ).
For example:
on = 1;
if (ioctl (myRouteSocket, FIONBIO, (int) &on) == -1) {
your response code for the ioctl call failure
}

Another socket option you might want to clear is the SO_USELOOPBACK option.
When this option is cleared, you will not hear the response to the messages that
you write to your socket.
on = 0;
if (setsockopt (myRtSock, SOL_SOCKET, SO_USELOOPBACK, (char *)&on,
sizeof (on)) == ERROR) {
your response code for the setsockopt call failure
}

A routing socket typically only sends a response if the requested operation fails.
The only exceptions are the GET messages, which also send a response with the
retrieved results (if successful). Thus, disabling this option will require a separate
routing socket to read the search results. Whether it is desirable or not to hear the
response is up to you. It can be good to monitor the response and thus check the
success or failure of the message that you wrote to the routing socket.

294
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

15.3 Preparing and Processing Routing Socket Messages


When preparing or processing a routing socket message, you can assume that it
consists of a fixed-length header followed by up to 8 socket address structures. For
most routing socket messages, the fixed-length header is described by an
rt_msghdr structure, which route.h defines as follows:
struct rt_msghdr {
u_short rtm_msglen; /* to skip over non-understood messages */
u_char rtm_version; /* future binary compatibility */
u_char rtm_type; /* message type */
u_short rtm_index; /* index for associated ifp */
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
pid_t rtm_pid; /* identify sender */
int rtm_seq; /* for sender to identify action */
int rtm_errno; /* why failed */
int rtm_use; /* from rtentry */
u_long rtm_inits; /* which metrics we are initializing */
struct rt_metrics rtm_rmx; /* metrics themselves */
};

This structure describes the fixed length message header for all but the following
routing socket message types:
#define RTM_NEWADDR 0xc /* address being added to interface */
#define RTM_DELADDR 0xd /* address being removed from interface */
#define RTM_IFINFO 0xe /* interface going up/down etc. */ 15
#define RTM_NEWMADDR 0xf /* mcast group membership added to if */
#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
#define RTM_IFANNOUNCE 0x11 /* iface arrival/departure */

For RTM_NEWADDR or RTM_DELADDR messages, the message header is


described by an ifa_msghdr structure, which if.h defines as follows:
/*
* Message format for use in obtaining information about interface
* addresses from getkerninfo and the routing socket
*/
struct ifa_msghdr {
u_short ifam_msglen; /* to skip over non-understood messages */
u_char ifam_version; /* future binary compatibility */
u_char ifam_type; /* message type */
int ifam_addrs; /* like rtm_addrs */
int ifam_flags; /* value of ifa_flags */
u_short ifam_index; /* index for associated ifp */
int ifam_metric; /* value of ifa_metric */
};

295
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

For an RTM_IFINFO message, the message header is described by an if_msghdr


structure, which if.h defines as follows:
/*
* Message format for use in obtaining information about interfaces
* from getkerninfo and the routing socket
*/
struct if_msghdr {
u_short ifm_msglen; /* to skip non-understood messages */
u_char ifm_version; /* future binary compatability */
u_char ifm_type; /* message type */
int ifm_addrs; /* like rtm_addrs */
int ifm_flags; /* value of if_flags */
u_short ifm_index; /* index for associated ifp */
struct if_data ifm_data;/* statistics and other data about if */
};

For RTM_NEWMADDR or RTM_DELMADDR messages, the message header is


described by an ifma_msghdr structure, which if.h defines as follows:
/*
* Message format for use in obtaining information about multicast
* addresses from the routing socket
*/
struct ifma_msghdr {
u_short ifmam_msglen; /* to skip over non-understood messages */
u_char ifmam_version; /* future binary compatability */
u_char ifmam_type; /* message type */
int ifmam_addrs; /* like rtm_addrs */
int ifmam_flags; /* value of ifa_flags */
u_short ifmam_index; /* index for associated ifp */
};

For RTM_IFANNOUNCE messages, the message header is described by an


if_announcemsghdr structure, which if.h defines as:
/*
* Message format announcing the arrival or departure of a network
* interface.
*/
struct if_announcemsghdr {
u_short ifan_msglen; /* to skip over non-understood messages */
u_char ifan_version; /* future binary compatibility */
u_char ifan_type; /* message type */
u_short ifan_index; /* index for associated ifp */
char ifan_name[IFNAMSIZ]; /* if name, e.g. "en0" */
u_short ifan_what; /* what type of announcement */
};

#define IFAN_ARRIVAL 0 /* interface arrival */


#define IFAN_DEPARTURE 1 /* interface departure */

296
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

15.3.1 Case/Switch Processing for Received Messages

The first three members of the routing socket message header structures are all of
the same type and carry the same meaning. Thus, when a message first arrives on
a socket, you can read the routing socket message type value using any structure
overlay that is convenient. To make it easier to do this, you could receive the
message into a union. Consider the following code fragment skeleton:1
union
{
struct rt_msghdr rtHdr; /* route message header */
struct if_msghdr ifHdr; /* interface message header */
struct ifa_msghdr ifaHdr; /* interface address message header */
struct ifma_msghdr ifmaHdr; /* new or delete multicast msg hdr */
struct if_announcemsghdr ifaAnnHdr; /* interface change anncmnt */
} aRtSockMsg; /* a routing socket message */

aRtSockMsg theRtSockMsg;
int count;
u_char cmd;

FOREVER
{
count = recv(myRtSock, (char *)&theRtSockMsg, sizeof(aRtSockMsg), 0);
if ( count <= 0) {return;}
if ( theRtSockMsg.rtHdr.rtm_version != RTM_VERSION )
{
response code for a routing socket version mis-match 15
}
cmd = theRtSockMsg.rtHdr.rtm_type;
switch (cmd)
{
case RTM_ADD:
response code
case RTM_DELETE:
response code
case RTM_CHANGE:
response code
case RTM_GET:
response code
case RTM_LOSING:
response code
case RTM_REDIRECT:
response code
case RTM_MISS:
response code
case RTM_LOCK:
response code
case RTM_RESOLVE:
response code

1. Although this union is useful for receiving messages, it would waste resources to use it
when creating a routing socket message.

297
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

case RTM_NEWADDR:
response code
case RTM_DELADDR:
response code
case RTM_IFINFO:
response code
case RTM_NEWMADDR:
response code
case RTM_DELMADDR:
response code
case RTM_IFANNOUNCE:
response code
case RTM_ADDEXTRA: /* DEPRECATED, enhanced message set only */
response code
case RTM_DELEXTRA: /* DEPRECATED, enhanced message set only */
response code
case RTM_NEWCHANGE: /* enhanced message set only */
response code
case RTM_NEWGET: /* DEPRECATED, enhanced message set only */
response code
case RTM_GETALL: /* enhanced message set only */
response code
case RTM_NEWIPROUTE: /* new, but present in all stacks */
response code
case RTM_OLDIPROUTE: /* new, but present in all stacks */
response code
default:
response code
} /* End of switch (cmd) */
} /* End of FOREVER */

This code skeleton includes both the standard routing socket message as well as
the enhanced message set, which is available only if you build the network stack
with the -DROUTER_STACK build option defined.

15.3.2 Types of Routing Socket Messages

Routing sockets on a VxWorks target running a host stack build use the standard
set of routing socket messages described in the routing sockets section of TCP/IP
Illustrated, Volume 2. Constants for these message types are defined in route.h as
follows:
#define RTM_ADD 0x1 /* add route */
#define RTM_DELETE 0x2 /* delete route */
#define RTM_CHANGE 0x3 /* change metrics or flags */
#define RTM_GET 0x4 /* report metrics */
#define RTM_LOSING 0x5 /* route suspected to be failing */
#define RTM_REDIRECT 0x6 /* told to use different route */
#define RTM_MISS 0x7 /* lookup failed on this address */
#define RTM_LOCK 0x8 /* lock specified metrics */
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */

298
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

#define RTM_RESOLVE 0xb /* required to resolve dest to LL addr */


#define RTM_NEWADDR 0xc /* address being added to interface */
#define RTM_DELADDR 0xd /* address being removed from interface */
#define RTM_IFINFO 0xe /* interface going up/down etc. */
#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
#define RTM_IFANNOUNCE 0x11 /* iface arrival/departure */

Of the messages above, only five are valid for transmission to the routing table.
These are:
#define RTM_ADD 0x1 /* add route */
#define RTM_CHANGE 0x3 /* change metrics or flags */
#define RTM_DELETE 0x2 /* delete route */
#define RTM_GET 0x4 /* report metrics */
#define RTM_LOCK 0x8 /* lock specified metrics */

The router stack build of the network stack supports an extension to the standard
routing socket message set so that it can report events associated with the route
table’s ability to store multiple redundant routes (routes to the same destination).
For the most part, these extra message types are available only in a router stack
build of the network stack. The exceptions to this are RTM_NEWIPROUTE, and
RTM_OLDIPROUTE, which can be used with all network stack variants.
The extra message types are as follows:
#define RTM_ADDEXTRA 0xf /* Report creation of duplicate route */
#define RTM_DELEXTRA 0x10 /* Report deletion of duplicate route */ 15
#define RTM_NEWCHANGE 0x11 /* Change gateway of duplicate rt */ sendable
#define RTM_NEWGET 0x12 /* Find any route with gateway */ sendable
#define RTM_GETALL 0x13 /* Get route to dst & duplicates */ sendable
#define RTM_NEWIPROUTE 0x14 /* Replacement for deleted primary IP rt */
#define RTM_OLDIPROUTE 0x15 /* Demoted IP rt replaced with new entry */

Of the extra message types listed immediately above, only those marked sendable
are valid for transmission to the routing table.
In addition, the router stack build of the network stack makes slight changes to the
behavior of the RTM_ADD and RTM_DELETE messages. The following sections
describe these two messages as well as the extra message types.

RTM_ADD

You can both read and write RTM_ADD messages.


■ Receiving an RTM_ADD Message

Receiving this message indicates that some agent has attempted to add a new
route to the routing table. To know whether the attempt succeeded or failed,
check the rt_msghdr.rtm_errno field.

299
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

If the route just added is a new interface route, an RTM_NEWADDR preceded


the RTM_ADD message.
To check whether the route was added as a primary route, test the
rt_msghdr.rtm_flags field for an RTF_PRIMARY flag. If the flag is present, the
route was added as a primary route. If this addition demoted an existing route
from the place of primary route, an RTM_OLDIPROUTE message preceded this
RTM_ADD message.
In previous releases of the router stack, an RTM_ADD message never occurred
in response to the addition of a secondary route. An added secondary route
was indicated by an RTM_ADDEXTRA message. In the current router stack, the
addition of a secondary route generates both an RTM_ADD and an
RTM_ADDEXTRA, which is now deprecated. RTM_ADDEXTRA will be
dropped in a future release.
■ Writing an RTM_ADD Message

Writing an RTM_ADD message adds a new route to the routing table if the
message is well formed and at least one of the following elements
distinguishes the new route from a route already existing in the table:
– destination address
– netmask value (or IPv6 prefix value)
– gateway
– protocol ID
– TOS
To monitor the success of an add request under the standard message set,
check the errno value, which is available from the send results.
The header for an RTM_ADD message is described by an rt_msghdr structure,
which is defined in route.h.

RTM_DELETE

You can both read and write RTM_DELETE messages.


■ Receiving an RTM_DELETE Message

Receiving this message indicates that some agent has tried to delete a route
from the routing table. To know whether the attempt succeeded, check the
rtm_errno field in the message header.
If the deleted route is an interface route, this RTM_DELETE is followed by an
RTM_DELADDR.

300
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

To check whether the deleted route was a primary route, test the
rt_msghdr.rtm_flags field for an RTF_PRIMARY flag.
If the flag is set, the deleted route was a primary route. This also means that
the deleted route was the only route for the destination/netmask. For a router
stack, if there had been at least one secondary route to the destination, this
RTM_DELETE would have been preceded by an RTM_NEWIPROUTE in which
the RTF_PRIMARY flag was set. Consequently in this (final) RTM_DELETE
message, the RTF_PRIMARY flag would not be set, although it was the primary
route before the deletion occurred.
Previously, an RTM_DELETE message never occurred in response to the
deletion of a secondary route. A deleted secondary route was indicated by an
RTM_DELEXTRA. In the current network stack, the deletion of a secondary
route generates both an RTM_DELETE and an RTM_DELEXTRA, which is now
deprecated. RTM_DELEXTRA will be dropped from the next major release.
■ Writing an RTM_DELETE Message

Writing an RTM_DELETE message deletes a route from the routing table if the
message is well formed and if it matches a route in the table. The criteria by
which a match is made are:
– destination address
– netmask value (or IPv6 prefix value) 15
– gateway (a value of NULL functions as a wildcard)
– protocol ID (a value of 0 functions as a wildcard)
– TOS (a value of -1 functions as a wildcard)
You need to specify a protocol ID, a TOS value, and a gateway value only if
you want to delete a secondary route. To delete the primary route, it is enough
to specify only the destination address and netmask value. You can use the full
set of identifiers if you want.
To check the success of a delete request, monitor the socket for an incoming
RTM_DELETE.
The header for an RTM_DELETE message is described by an rt_msghdr structure,
which is defined in route.h.

RTM_GET

You can both read and write RTM_GET messages. Writing this message checks the
route table for a route to the specified destination. To check the success of the
request, monitor the socket for an incoming RTM_GET message. If the request was
successful, the route information is appended to the message header. If the request

301
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

failed to find a matching route, this is indicated in the rtm_errno field of the
message header.
The criteria by which a match is made are:
– destination address
– netmask value (or IPv6 prefix value)
– gateway (a value of NULL functions as a wildcard)
– protocol ID (a value of 0 functions as a wildcard)
– TOS (a value of -1 functions as a wildcard)
You need to specify the protocol ID, the TOS value, and the gateway value only if
you want to retrieve a secondary route. To retrieve the primary route, you need
specify only the destination address and netmask (or prefix) value.
The header for an RTM_GET message is described by an rt_msghdr structure,
which is defined in route.h.

RTM_LOSING

This is a read-only message. It indicates that the specified route might not still be
valid. TCP originates this message after four or more consecutive failed
retransmissions over the route.
The header for an RTM_LOSING message is described by an rt_msghdr structure,
which is defined in route.h.

RTM_REDIRECT

This is a read-only message. It indicates that ICMP has sent a redirect for the
specified destination, the address appended to the header in the RTA_DST
location. The address of a preferred gateway is appended to the message in the
RTA_GATEWAY location. The address of the author for the redirect message is
appended to the header in the RTA_AUTHOR location.
To know whether this message indicates a change in the contents of the route table,
check the rtm_errno value in the message header. A non-zero rtm_errno value
indicates a failed RTM_REDIRECT. A zero indicates a successful RTM_REDIRECT.
In this case, the table will contain a new host-specific route. This new host route is
created only if the original mis-directed route was a non-host (or network) route.
Otherwise, that existing host route is modified.
The header for an RTM_REDIRECT message is described by an rt_msghdr
structure, which is defined in route.h.

302
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

RTM_MISS

This is a read-only message. It indicates that some agent’s search of the route table
failed to find a route to the specified destination. The header for an RTM_MISS
message is described by an rt_msghdr structure, which is defined in route.h.

RTM_LOCK

You can both read and write RTM_LOCK messages. Receiving this message
indicates that the metrics associated with the specified route are now locked.
Writing this message locks the metrics for the specified route. The header for an
RTM_LOCK message is described by an rt_msghdr structure, which is defined in
route.h.

RTM_CHANGE

You can both read and write RTM_CHANGE messages.


■ Receiving an RTM_CHANGE Message

Receiving this message indicates that an agent has changed the gateway,
metrics, or some other property associated with the route to the specified
destination.
■ Writing an RTM_CHANGE Message
15
Writing this message lets you change the gateway or metrics associated with
the route to the specified destination, which is identified by:
– destination address
– netmask value (or IPv6 prefix value)
– gateway (a value of NULL does not function as a wildcard)
– protocol ID (a value of 0 functions as a wildcard)
– TOS (a value of -1 functions as a wildcard)
You need to specify a protocol ID and TOS value only if you want to modify a
particular route. You can set these to wildcard values if matching on them is
not important to you. If multiple routes exist, you must specify a gateway in
order to select the matching entry.
All information in the message other than the destination and netmask are
interpreted as values that you want written into the existing route entry. If
only one route exists for a destination address and netmask, you can change
the gateway by providing a new gateway value. If multiple routes exist, then
you cannot change the gateway because the gateway is used to select the route
that is the entry you want changed.

303
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The header for an RTM_CHANGE message is described by an rt_msghdr structure,


which is defined in route.h.

RTM_NEWADDR

This is a read-only message. This message is the first of two messages associated
with adding an IP address to an interface. The second, an RTM_ADD, describes the
route through that interface to the subnet associated with the address.
For an RTM_NEWADDR message, the message header is described by an
ifa_msghdr structure, which is defined in if.h.

RTM_DELADDR

This is a read-only message. This message is the second of two messages associated
with deleting an IP address from an interface. The first, an RTM_DELETE, describes
the now deleted route through that interface to the subnet with the associated
address.
For an RTM_DELADDR message, the message header is described by an
ifa_msghdr structure, which is defined in if.h.

RTM_IFINFO

This is a read-only message. This message reports a change in status for the
specified interface. All routes through that interface are affected by the change. For
an RTM_IFINFO message, the message header is described by an if_msghdr
structure, which is defined in if.h.

RTM_NEWMADDR

You can both read and write RTM_NEWMADDR messages. By writing this type of
message, you can add a multicast group membership to an interface. Receiving
this message indicates that a group membership has been added to an interface.
For an RTM_NEWMADDR message, the message header is described by an
ifma_msghdr structure, which is defined in if.h.

RTM_DELMADDR

You can both read and write RTM_DELMADDR messages. By writing this type of
message, you can delete a multicast group membership from an interface.
Receiving this message indicates that a group membership has been deleted from
an interface. For an RTM_DELMADDR message, the message header is described
by an ifma_msghdr structure, which is defined in if.h.

304
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

RTM_IFANNOUNCE

This is a read-only message. It announces the arrival or departure of a network


interface. The header for an RTM_IFANNOUNCE message is described by an
if_announcemsghdr structure, which is defined in if.h.

RTM_ADDEXTRA

Although still supported, this is a deprecated message. It will not be supported


after the next major release of the network stack. This read-only message indicates
the addition of a secondary route.
In the current stack, any event that generates an RTM_ADDEXTRA also generates
an RTM_ADD. Previously, the event that generated an RTM_ADDEXTRA did not
generate RTM_ADD. You may need to accommodate this change in any state
machine built upon the previous behavior. In addition, you should, if possible,
anticipate the eventual removal of the RTM_ADDEXTRA message.

RTM_DELEXTRA

Although still supported, this is a deprecated message. It will not be supported


after the next major release of the stack. This read-only message indicates the
deletion of a secondary route.
In the current stack, any event that generates an RTM_DELEXTRA also generates 15
an RTM_DELETE. Previously, the event that generated an RTM_DELEXTRA did not
generate RTM_DELETE. You may need to accommodate this change in any state
machine built upon the previous behavior. In addition, you should, if possible,
anticipate the eventual removal of the RTM_DELEXTRA message.

RTM_NEWCHANGE

This is a message from the enhanced message set pulled in when you compile the
stack using the -DROUTER_STACK option. You can both read and write
RTM_NEWCHANGE messages.
■ Receiving an RTM_NEWCHANGE Message

Receiving this message indicates that an agent has changed the gateway,
metrics, or some other property associated with the route to the specified
destination. The format of the message is similar to but not identical to that of
an RTM_CHANGE. If the agent changed the gateway, the message must
provide you with both the new and old gateway addresses. The new gateway
address is reported in the standard gateway location. The old gateway address
is reported in the RTAX_AUTHOR location.

305
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


Writing an RTM_NEWCHANGE Message

When writing an RTM_NEWCHANGE message to a socket, you identify the


route table entry that you want to change using the following values:
– destination address
– netmask value (or IPv6 prefix value)
– gateway (a value of NULL routines as a wildcard)
– protocol ID (a value of 0 functions as a wildcard)
– TOS (a value of -1 functions as a wildcard)
When specifying the gateway of the existing route entry that you want to
change, append the address to the RTAX_AUTHOR location not the
RTAX_GATEWAY location. If you write an address other than NULL to the
RTAX_GATEWAY location, the system assumes that you want to change the
gateway value stored in the record. This behavior parallels the RTM_CHANGE
behavior.
All values in the message other than the five identifiers listed above are
assumed to be values that you want written into the route table entry specified
by the five identifiers.
The header for an RTM_NEWCHANGE message is described by an rt_msghdr
structure, which is defined in route.h.

RTM_NEWGET

Although still supported, this is a deprecated message. It will not be supported in


the next major release of the network stack. In previous releases of the stack, an
RTM_GET write could not include all the information needed to identify a
secondary route. Thus, it could retrieve only a primary route entry. To work
around this limitation, you used an RTM_NEWGET message. Under the current
stack, this limitation on the RTM_GET message no longer applies. Thus, under the
current stack, use RTM_GET instead of RTM_NEWGET.

RTM_GETALL

This is a message from the enhanced message set pulled in when you compile the
stack using the -DROUTER_STACK option. Writing an RTM_GETALL is the same
as writing an RTM_GET. The response is an RTM_GETALL message that includes
descriptions for all route entries for the specified destination, TOS, and protocol.
To retrieve a list of all routes for the specified destination, use wildcard values for
the TOS and protocol (-1 and 0 respectively).

306
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

To read the route descriptions in a received RTM_GETALL message, start after the
routing socket header. There you will find:

a destination address

gateway addresses for all matches

a netmask
Use successive sockaddr_gate structures (if working with IPv4) or successive
sockaddr_gate6 structures (if working with IPv6) to interpret the data between the
destination address and the netmask. Use this special structure overlay to access
the route weight, protocol ID, and the RFC 1213 metrics for the route associated
with each gateway address.
The sockaddr_gate structure is defined in route.h as follows:
struct sockaddr_gate
{
u_char gate_len;
u_char gate_family;
u_char routeProto;
u_char weight;
u_long gate_addr;
long value1;
long value2;
long value3;
long value4;
long value5; 15
long routeTag;
long routeTos;
struct sockaddr * ifa;
struct sockaddr * ifp;
};

The sockaddr_gate6 structure is defined in route.h as follows:


struct sockaddr_gate6
{
u_char gate_len;
u_char gate_family;
u_char routeProto;
u_char weight;
long value1;
struct in6_addr gate6_addr;
long value2;
long value3;
long value4;
long value5;
long routeTag;
long routeTos;
struct sockaddr * ifa;
struct sockaddr * ifp;
};

307
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The weight field of these structures is relevant only if you are working with the
enhanced message set.

RTM_OLDIPROUTE

This is a read-only message. Receiving an RTM_OLDIPROUTE indicates that the


route described in the message is the old primary route that has been demoted to
secondary route status. This change in status is not the result of any change to the
old primary route itself. Instead, it occurred either because an agent added a new
lower-weight route or because an agent reduced the weight of a secondary route
to a value less than that of the old primary route.
RTM_OLDIPROUTE does not occur in isolation but is the first of a pair. The next
message must be RTM_NEWCHANGE, RTM_CHANGE, or RTM_ADD. Any other
message indicates an error. These follow up messages tell you whether the new
primary route resulted from changing an existing secondary route or adding a new
route.

RTM_NEWIPROUTE

This is a read-only message. Receiving an RTM_NEWIPROUTE indicates that the


route described in the message is the new primary route for the destination. This
event occurs when an agent deletes the old primary route. If the stack was built
using the -DROUTER_STACK option, this event can also occur if some agent
increases the weight of a primary route to a value above that of a secondary route.
RTM_NEWIPROUTE does not occur in isolation but is the first of a pair. The next
message must be either RTM_CHANGE or RTM_DELETE. Any other message
indicates an error. These follow up messages tell you whether the new primary
route resulted from deleting or changing the previous primary route. In addition,
the RTF_PRIMARY flag is not set in these RTM_DELETE or RTM_CHANGE
messages. This is because the previous primary route has been superseded by the
“new” route.

15.3.3 RTF Flags

The RTF flags indicate a route's type and other attributes. The various flags are can
be used differently, depending on circumstance. The following is a complete
listing of the supported RTF_name flags.

308
15 Working with Routing Sockets
15.3 Preparing and Processing Routing Socket Messages

Table 15-1 RTF Flags

Flag Hex Value Description

RTF_UP 0x1 Route is up and usable.

RTF_GATEWAY 0x2 Destination is reachable through a


gateway.

RTF_HOST 0x4 Route to a host.

RTF_REJECT 0x8 Host or net unreachable. Usually set


when the MAC address cannot be
resolved.

RTF_DYNAMIC 0x10 Created dynamically (by redirect).

RTF_MODIFIED 0x20 Modified dynamically (by redirect).

RTF_DONE 0x40 Message confirmed (applies to routing


sockets). The routing socket message has
been processed.

RTF_NO_MSGS RTF_DONE Tells the RTM to not generate routing


messages 15

RTF_DELCLONE 0x80 Delete cloned route.

RTF_INTF_ROUTE RTF_DELCLONE Used to indicate to rtrequest that this is


an interface route.

RTF_CLONING 0x100 .Generate new routes on use. This flag is


usually set internally for directly
connected network routes. This causes
ARP entries to be cloned.

RTF_XRESOLVE 0x200 External daemon resolves name. This


specifies that a cloned route be passed to
a user daemon through a RTM_MISS
message for name resolution.

RTF_LLINFO 0x400 Route contains link layer information


generated by link layer (for example,
ARP).

309
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 15-1 RTF Flags

Flag Hex Value Description

RTF_STATIC 0x800 Manually added (through routec( ), for


example).

RTF_BLACKHOLE 0x1000 Just discard packets (during updates).

RTF_MGMT 0x2000 Modified by management protocol.

RTF_PROTO2 0x4000 Protocol specific routing flag.

RTF_PROTO1 0x6000 Protocol specific routing flag.

RTF_PRCLONING 0x10000 Protocol requires cloning. For IP, all


unicast non-host, non-cloned routes
have this flag set.

RTF_WASCLONED 0x20000 Route generated through cloning.

RTF_PROTO3 x40000 Protocol specific routing flag.

RTF_LOCAL 0x200000 Route represents a local address.

RTF_BROADCAST 0x400000 Route represents a broadcast address.

RTF_MULTICAST 0x800000 Route represents a multicast address.

RTF_LLNOTAVAIL 0x1000000 Link layer not available, for example, if


the interface is down.

RTF_PRIMARY 0x2000000 Primary route, used for forwarding.

15.4 Extracting Information from a Routing Socket Message


Included in a routing socket message is all the information needed to identify a
route table entry. This includes information such as the destination address,
netmask, and gateway (which are appended after the message header) as well as
the route metrics (which are supplied in the members of the message header).
After the header, a routing socket message can contain up to 8 socket address
structures.

310
15 Working with Routing Sockets
15.4 Extracting Information from a Routing Socket Message

In all received messages except an RTM_GETALL message, the TOS value and
protocol ID value are embedded in the socket address structure that provides the
destination address. For more on how to extract information from an
RTM_GETALL message, see RTM_GETALL, p.306.

15.4.1 Parsing the Routing Socket Message after the Header

If all 8 socket address structures were present in a message, the structures would
follow the header in the order shown below:
■ destination address
■ gateway address
■ netmask
■ cloning mask
■ interface name
■ interface address
■ address of the author of a redirect
■ broadcast or point-to-point destination address
These appended socket address structures supply all the remaining information
needed to identify a route table entry for the events (add, change, delete, and so
on.) associated with that route.
15
To tell you which addresses are actually included and which are omitted, the
routing socket message header provides an 8-bit mask. The name of the field that
contains this bit-mask is of the form: structure_addrs, where structure is rtm, ifm,
ifmam, or ifam. Each bit in the mask corresponds to one of the 8 addresses listed
above. If the bit is set, the address is present. If the bit is clear, the address is
omitted.
Consider a bit-mask of 0x87, which is 1000 0111 in base 2. In this mask, only four
bits are set, which tells you that the message after the header contains only four
addresses. Because the lowest order bit is set, you know that the first address after
the header is a destination address. Because the second and third lowest order bits
are set, you know that the second address is a gateway address, which is followed
by a netmask. The only other set bit is the highest order bit, which tells you that the
final (fourth address) is a broadcast address.

311
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

For convenience, route.h defines a set of constants for the bits in a structure_addrs,
mask. You can AND these constants against structure_addrs to test whether a
particular address is present in the message. These constants are as follows:
#define RTA_DST 0x1 /* destination sockaddr present */
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
#define RTA_IFP 0x10 /* interface name sockaddr present */
#define RTA_IFA 0x20 /* interface addr sockaddr present */
#define RTA_AUTHOR 0x40 /* sockaddr of redirect author or other */
#define RTA_BRD 0x80 /* for NEWADDR, brdcst or p-p dest addr */

In addition to knowing something about the contents of the routing socket


message, it is useful to have pointers to the different sockaddr structures within
the message. To store these pointers, consider an rt_addrinfo structure, which
route.h defines as follows:
struct rt_addrinfo {
int rti_addrs;
struct sockaddr *rti_info[RTAX_MAX];
};

The RTAX_MAX constant is defined in route.h as 8, the maximum number of


socket address structure types included in a routing socket message. As a
convenience, route.h also defines constants for indexing into the
rt_addrinfo.rti_info[ ] array of pointers to sockaddr structures. These constants
are:
#define RTAX_DST 0 /* destination sockaddr present */
#define RTAX_GATEWAY 1 /* gateway sockaddr present */
#define RTAX_NETMASK 2 /* netmask sockaddr present */
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
#define RTAX_IFP 4 /* interface name sockaddr present */
#define RTAX_IFA 5 /* interface addr sockaddr present */
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
#define RTAX_BRD 7 /* for NEWADDR, brdcst or p-p dest addr */
#define RTAX_MAX 8 /* number of array elements */

To populate the rt_addrinfo.rti_info[ ] array when working with routing sockets,


consider implementing a routine and macro similar to the following:2
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof (long) - 1))) : sizeof (long
))

void routingSocketAddressesGet(
struct rt_addrinfo *pRtAddrInfo, /* output, & _addrs mask */
struct sockaddr *pStartSockAddr, /* start of socket addresses */

2. This ROUNDUP( ) macro expresses “a” twice. Thus, inputs such as “foo++” evaluate twice,
which might not be what you intend.

312
15 Working with Routing Sockets
15.4 Extracting Information from a Routing Socket Message

{
int i;

for (i = 0; i < RTAX_MAX; i++) {


if (pRtAddrInfo->rti_addrs & (1 << i) ) {
pRtAddrInfo->rti_info[i] = pStartSockAddr;
pStartSockAddr += ROUNDUP( pStartSockAddr->sa_len )
} else
pRtAddrInfo->rti_info [i] = NULL;
}
}

The purpose of the ROUNDUP( ) macro call is to advance the pointer by the size of
a socket address structure rounded up to the next four-byte multiple. The main
reason for rounding up to the next four-byte multiple is that this is consistent with
how the message is constructed in the BSD routing socket implementation.
When calling a routine such as that above to extract the addresses from a routing
socket message received into a union such as:
union
{
struct rt_msghdr rtHdr; /* route message header */
struct if_msghdr ifHdr; /* interface message header */
struct ifa_msghdr ifaHdr; /* interface address message header */
} aRtSockMsg; /* routing socket message */
15
Assuming that you have previously declared and allocated:
struct rt_addrinfo rtAddrInfo;

You would make calls such as:


struct sockaddr *pFirstSockAddr = RtSocketMsg.rtHdr + sizeof(rtm_msghdr);
rtAddrInfo.rti_addrs = aRtSocketMsg.rtMsg.rtm_addrs;

routingSocketAddressesGet ( &rtAddrInfo, pFirstSockAddr );

When extracting the messages from a routing socket message that uses an
if_msghdr or an ifa_msghdr, keep in mind that these structures are not necessarily
the same size as the rt_msghdr. Thus, you would have to adjust the calculation of
pFirstSockAddr with a sizeof( ) call for the appropriate structure.

15.4.2 Extracting TOS and Protocol IDs from a Received Message

In received messages, the TOS value and protocol ID value are embedded in the
socket address structure that provides the destination address. You can use the
TOS_GET( ) and RT_PROTO_GET( ) macros to extract the TOS value or the protocol
ID from this socket address structure.

313
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

These macros are defined in route.h as follows:


#define TOS_GET(pSockaddr) (((struct sockaddr_rt *)(pSockaddr))->srt_tos)

#define RT_PROTO_GET(pSockaddr) \
(((struct sockaddr_rt *)(pSockaddr))->srt_proto)

A value of -1 for TOS indicates that the sender did not want to specify a TOS value.
Similarly, a value of 0 for the protocol ID indicates that the sender did not want to
specify a protocol ID.

15.5 Building a Routing Socket Message


The messages you can transmit over a routing socket are restricted to five basic
types. The -DROUTER_STACK build option provides an additional three messages
from the extended message set.:
#define RTM_ADD 0x1 /* add route */
#define RTM_CHANGE 0x3 /* change metrics or flags */
#define RTM_DELETE 0x2 /* delete route */
#define RTM_GET 0x4 /* report route, report metrics */
#define RTM_LOCK 0x8 /* lock specified metrics */

#ifdef ROUTER_STACK
#define RTM_NEWCHANGE 0x12 /* Change gateway of duplicate route */
#define RTM_NEWGET 0x13 /* Find any route with gateway */
#define RTM_GETALL 0x14 /* Get IP route to dst and duplicates */
#endif /* ROUTER_STACK */

Within these messages, you specify a route table entry using the following values:

a destination address, in the RTAX_DST socket address structure

a netmask, in the RTAX_NETMASK socket address structure

a gateway address, in the RTAX_GATEWAY socket address structure

a TOS value, in the RTAX_DST socket address structure (optional)

a Protocol ID, in the RTAX_DST socket address structure (optional)
The socket address structures referred to above are appended after the routing
socket message header.
To specify route metrics in the routing socket message, use the rt_metrics structure
in the rtm_rmx field of the routing socket message header. For more information,
see rtm_rmx – optional, for setting metrics, p.318.

314
15 Working with Routing Sockets
15.5 Building a Routing Socket Message

NOTE: Depending on the message type and whether the table stores more than one
entry for a destination, you may need to specify a destination address only, or a
destination and netmask only, or a gateway value.

15.5.1 Setting the Header Structure Field Values

Each of the writable routing socket message types use an rt_msghdr structure for
its header. When building a routing socket message, fill in the rt_msghdr members
as follows:
rtm_msglen – required in an outgoing message
Expects the length of the entire socket message. The reported size includes the
header plus all appended socket addressees. The best time to assign this value
is after you have appended the last address to the routing socket message. See
below, rtm_addrs – required in an outgoing message, p.316.
rtm_version – required in an outgoing message
Expects the version ID of the routing socket message. Under VxWorks, there
is only one valid value for this field, RTM_VERSION, which is defined in
route.h.
rtm_type – required in an outgoing message 15
Expects a value indicating the routing socket message type:
RTM_ADD – add a route
RTM_CHANGE – change the metrics for a route
RTM_DELETE – delete a route
RTM_GET – get the route for the specified destination
RTM_LOCK – lock the metrics associated with the specified route
If you built the network stack using the -DROUTER_STACK build option,
the following are also valid:
RTM_NEWCHANGE – change gateway of duplicate route
RTM_NEWGET – find any route with gateway
RTM_GETALL – get IP route to destination and duplicates
These message types (described 15.3.2 Types of Routing Socket Messages, p.298)
let you add, change, delete, get, or lock an entry in the route table. The
response to an add, change, lock, get, or delete message is an incoming add,
change, lock, get, or delete message on your socket. You can determine the
success or failure of your request by reading the rtm_errno field in the header
of the response message.

315
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

rtm_index – read-only, ignored in outgoing messages


The index value for the associated network interface.
rtm_flags – for add and delete messages only
In an outgoing message, this field expects an integer value whose bits describe
the route. Included in this value are bits that indicate whether the interface is
online or offline, whether this is a host route or a gateway route, and more. For
a complete listing of valid flags, see 15.3.3 RTF Flags, p.308.
In an outgoing message, the flags likely to interest you most are RTF_HOST
and RTF_GATEWAY.
RTF_HOST
Indicates a host route when set, a network route otherwise. If you
specify this flag, you must also provide a NULL netmask (that is, no
netmask).
RTF_GATEWAY
Indicates an indirect route when set, a direct route otherwise.
In an incoming message, the flag likely to interest you most is RTF_PRIMARY.
If present, this flag indicates that the added or deleted route is (or was) a
primary route. Otherwise, the route is (or was) a secondary route.
The RTF_* constants used in the flags value are defined in route.h.
rtm_addrs – required in an outgoing message
Expects a bit mask in which you have set bits that identify which addresses
you have appended to the end of this message. To help set these bits as you
append addresses to the message, consider creating infrastructure similar to
the following:
struct {
struct rt_msghdr msgHdr;
char msgPayload[512];
} aRtSockMsg; /* structure for a routing socket message */

#define NEXTADDR ( BitToSet, Mask, SockAddr, NextAddrStart, Length


) \
{ \
Length = ROUNDUP(SockAddr.sa.sa_len); \
bcopy( (char *)&(SockAddr), NextAddrStart, Length); \
NextAddrStart += Length;\
Mask |= (BitToSet); \
}

316
15 Working with Routing Sockets
15.5 Building a Routing Socket Message

With the above already defined, and assuming you have already allocated and
appropriately populated instances of so_dst, so_gate, so_mask, and the other
elements you need to include in the message, you could do the following:
struct aRtSockMsg theRtSockMsg;
char * theNextAddrStart = theRtSockMsg.msgPayload;
int appendedLength = 0;
bzero((char *)&theRtSockMsg, sizeof(aRtSockMsg));

NEXTADDR (
RTA_DST, /* type of address appended */
theRtSockMsg.msgHdr.rtm_addrs, /* mask of addr types in msg */
so_dst, /* address to append to msg */
theNextAddrStart, /* where address is appended */
appendedLength /* length just added to msg */
);

This macro call would append the destination address in so_dst to the
message space after the header in theRtSockMsg. It would also set the
RTA_DST bit in theRtSockMsg.msgHdr.rtm_addrs.3

Leaving theNextAddrStart at its current value, you would then follow this
with NEXTADDR( ) calls for all the addresses that you want to append in the
appropriate order. It is critical that you get the order correct and that you do
not accidentally append the same element more than once. The correct order
is as follows:
15
RTA_DST – destination address
RTA_GATEWAY – gateway address
RTA_NETMASK – netmask
RTA_GENMASK – cloning mask
RTA_IFP – interface name
RTA_IFA – interface address
RTA_AUTHOR – address of author of redirect
RTA_BRD – broadcast or point-to-point destination address
You are also now ready to set the value of rtm_msglen:
theRtSockMsg.msgHdr.rtm_msglen = (char *)theNextAddrStart
- (char *)&theRtSockMsg;

rtm_pid – optional in an outgoing message


A process or task ID or some other identifier for yourself. You can use this to
recognize responses to the commands you have issued.

3. Do not forget that NEXTADDR( ) is a macro not a C routine. Thus, it can (and, in this case,
must) change the value supplied for theNextAddrStart.

317
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

rtm_seq – optional in an outgoing message


Expects the sequence number that you want to assign to this command. This
value is returned in the response message. Use it to help distinguish the
response to this command from responses to other commands.
rtm_errno – read-only in an outgoing message
Read this value in the response to a command. If its value is zero, the
command was successful. Any other value indicates an error. Use errnoGet( ).
rtm_use – read-only in an outgoing message
This is strictly an output vehicle. It tells you the number of times that the
specified route was used.
rtm_inits – optional, for setting metrics
Expects a value whose bits indicate which metrics this message would
initialize. Use the RTV_ constants defined in route.h to help set bits for this
field.
/*
* Bitmask values for rtm_inits and rmx_locks.
*/
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
#define RTV_EXPIRE 0x4 /* init or lock _expire */
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
#define RTV_RTT 0x40 /* init or lock _rtt */
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */

rtm_rmx – optional, for setting metrics


The rtm_rmx field expects an rt_metrics structure, defined in route.h as:
/*
* These numbers are used by reliable protocols for determining
* retransmission behavior and are included in the routing structure.
*/
struct rt_metrics {
u_long rmx_locks; /* Kernel must leave these values alone */
u_long rmx_mtu; /* MTU for this path */
u_long rmx_hopcount; /* max hops expected */
u_long rmx_expire; /* lifetime for route, e.g. redirect */
u_long rmx_recvpipe; /* inbound delay-bandwidth product */
u_long rmx_sendpipe; /* outbound delay-bandwidth product */
u_long rmx_ssthresh; /* outbound gateway buffer limit */
u_long rmx_rtt; /* estimated round trip time */
u_long rmx_rttvar; /* estimated rtt variance */
u_long rmx_pksent; /* packets sent using this route */
u_long rmx_filler[5]; /* will be used for T/TCP later */
/* the last field is used for storing */
/* the last modification of the route */

318
15 Working with Routing Sockets
15.5 Building a Routing Socket Message

/* Additional WRN metrics for routing protocols */

long value1;
long value2;
long value3;
long value4;
long value5;
long routeTag;
u_long weight;
};
If you use this structure to specify metric values for a route, you must also set
the appropriate flags in the rtm_inits field.

15.5.2 Setting the TOS and Protocol Values in a Routing Socket Message

When preparing the socket address structure containing the destination address,
you must embed both a TOS value and a protocol ID. To do this, use the
TOS_SET( ) and RT_PROTO_SET( ) macros, which are defined in route.h as
follows:
#define TOS_SET(pSockaddr, tosVal)
(((struct sockaddr_rt *)(pSockaddr))->srt_tos = tosVal)

#define RT_PROTO_SET(pSockaddr, proto) \


(((struct sockaddr_rt *)(pSockaddr))->srt_proto = proto)
15
If the TOS value is irrelevant, specify a TOS value of -1. Similarly, if the protocol
ID is irrelevant, specify a protocol ID value of 0 (zero). For all operations other than
RTM_ADD, these values function as wild cards. For an RTM_ADD, these values are
never irrelevant. Thus, for an RTM_ADD, you must specify valid TOS and protocol
ID values.

319
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

320
16
Adding Routing Support
RIP, ARP, NDP, and ICMPv4

16.1 Introduction 321


16.2 Selecting a Route Storage Mechanism 323
16.3 Configuring VxWorks for Route Storage 324
16.4 Working with RIP 326
16.5 Adding RIPng Support 338
16.6 Adding ARP and NDP Support 342
16.7 Using the ICMPv4 Router Discovery Server 347

16.1 Introduction
This chapter describes how to select a route table storage mechanism. It also
describes some of the protocols used to maintain the contents of the route table.

Implementation

The route table implementation included with the Wind River Network Stack
supports the storage of multiple same-destination same-mask routes provided the
routes differ by a gateway value, TOS value, or protocol value. When IP queries
the route table, it expects to get back only one route. To satisfy this expectation, the
route table ranks multiple same-destination routes. The highest ranked route,

321
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

known as the primary route for the destination, is the route reported to IP. How
the system ranks same-destination routes depends on how you build the code.
In the route table produced by a host stack build, multiple same-destination routes
are ranked by age. The oldest route is the primary route. All newer routes are
ranked below the primary route according to age.
If the ability to store multiple same-destination routes is not required for your
application, and if you need to minimize the footprint of the routing table, you can
rebuild the network stack code to eliminate multi-route support. For more
information on this build option, see the Wind River Platforms Getting Started.

Storage Mechanisms

In addition, you can choose among three route table storage mechanisms. One
storage mechanism uses a PATRICIA1 tree to store routes. This is a good solution
for tables of moderate size. For very large tables, Wind River provides an AVL
storage mechanism. For very small route tables, Wind River provides a linked-list
storage mechanism. For more information, see 16.2 Selecting a Route Storage
Mechanism, p.323.
To add or remove routes from the route table, you can use a routing socket
connection or the routec( ) routine.
By default, the route table is able to store multiple same-destination routes. For
IPv4, a PATRICIA tree serves as the default storage mechanism. For IPv6, the
default is an AVL (Adelson-Velskii and Landis balanced binary search) tree. For
both IPv6 and IPv4, you can change the storage mechanism. You can use a simple
linked list as the storage mechanism instead of a PATRICIA or AVL tree, but only
if you expect to need only a very small table.
If reducing the image size is critical, you can recompile the route table source code
to eliminate support for storing multiple same-destination routes.

1. Donald R. Morrison, PATRICIA - Practical Algorithm to Retrieve Information Coded in


Alphanumeric, Journal of the ACM, 15(4):514-534, October 1968

322
16 Adding Routing Support
16.2 Selecting a Route Storage Mechanism

16.2 Selecting a Route Storage Mechanism


The Wind River Network Stack is a dual IPv4/IPv6 stack that can run in an
IPv4-only mode or dual IPv4/IPv6 mode. When running in dual mode, it
maintains both an IPv4 and an IPv6 route table. The storage mechanisms used for
these routing tables are individually configurable using the parameters
IPV4_RT_DISP_TBL, for the IPv4 table, and IPV6_RT_DISP_TBL, for the IPv6 table.
These parameters expect a pointer to an ipRouteDispatchTable structure
populated with pointers to routines that implement the route table storage
mechanism. You can supply a custom-written implementation of your own, or you
can use one of the three supplied by Wind River. The three supplied by Wind River
implement an AVL tree, a PATRICIA tree, and a simple linked list.
AVL Tree
If you require a very large route table, you can improve performance if you use
the route storage mechanism supplied by avlRibDispatchTable, which
references routines that implement an AVL tree to store routes. An AVL tree
outperforms a PATRICIA tree if the route table is very large.
The structure at avlRibDispatchTable is populated in avlRouteNodeLib.c,
which also defines the routines in avlRibDispatchTable.
PATRICIA Tree
If you require a route table that is not exceptionally large, you can save on
memory (compared to the AVL storage mechanism) if you use the route 16
storage mechanism supplied by ptRibDispatchTable, which references
routines that implement a PATRICIA tree.
The structure at ptRibDispatchTable is populated in ptRouteNodeLib.c,
which also defines the routines in ptRibDispatchTable.
Linked List
If you require a route table that needs to store only a very small number of
entries (including all generated ARP entries), you can save on memory
(compared to the AVL or PATRICIA tree storage mechanisms) if you use the
route storage mechanism supplied by llRibDispatchTable, which references
routines that implement a simple linked-list storage mechanism. This
mechanism is appropriate for small route tables only, such as for an edge
device that requires a routing table of under 10 elements. If the table grows too
large, performance degrades significantly, particularly when forwarding
traffic.
The structure at llRibDispatchTable is populated in llRouteNodeLib.c, which
also defines the routines in llRibDispatchTable.

323
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

If none of these route table storage mechanisms is appropriate to your needs, you
may implement your own. Your implementation must support the entry points
expected in an ipRouteDispatchTable structure, and those entry points must
conform to the APIs shown in ptRouteNodeLib.c, avlRouteNodeLib.c, and
llRouteNodeLib.c.

16.3 Configuring VxWorks for Route Storage


The Wind River Network Stack supports the following NFS client configuration
components, which you can use to include the modules needed to create an NFS
client:

Route Storage

Network Route Show Routines
These components are listed under the
Network Components > Network Private Components and
Network Components > Network Utility Components >
Show Routine Components folders in Workbench.

Route Storage

The INCLUDE_ROUTE_STORAGE component is automatically included when you


include the IPv4 or IPv6 configuration components. This component pulls in
ipRouteLib, the library that implements the route table manager.
The INCLUDE_ROUTE_STORAGE component contains the following
configuration parameter:

ROUTE_DEFAULT_WEIGHT

Synopsis: Default route weight, applied when the user does not specify one.
Default: 100

324
16 Adding Routing Support
16.3 Configuring VxWorks for Route Storage

Network Route Show Routines

The INCLUDE_NET_ROUTE_SHOW component pulls in the routeShow library,


which supplies the routeShow( ), routestatShow( ), mRouteShow( ), and
arpShow( ) routines. Including INCLUDE_NET_ROUTE_SHOW in a VxWorks
image sets up a call to the routeShowInit( ) initialization routine, which is defined
in:
installDir/vxworks-6.n/target/src/wrn/coreip/common/utilslib/routeShow.c
While gathering information, the route show routines walk the route table and
necessarily take splnet (the semaphore for the network stack). If they write their
output to a file descriptor while holding splnet, there is a risk of deadlock.
Deadlock results if writing to the file descriptor blocks waiting for some other task
to take splnet (which cannot happen because the routeShow library already has
it). For example, this can happen when calling routeShow( ) from the shell through
a telnet session, or when using WDB over the network. 2
To avoid the deadlock, the routines of the routeShow library can buffer their
output using snprintf( ) while holding splnet, then print later. This is the default
behavior. Alternatively, they can use the nonblocking logging facility,
nbioLogLib, to buffer the output. If there is no fear of conflict over splnet, you can
use the original (unbuffered) method of printf( ). This method is safe only if you
know that the output always goes to a file descriptor that does not require another
task to take splnet (for example, a serial console session). This unbuffered option
16
can be dangerous when using telnet or WDB over the network.
To select the buffering method, you can use one of the build-time defines:
■ INCLUDE_NET_ROUTE_SHOW_SNPRINTF (use snprintf( ) buffering)
■ INCLUDE_NET_ROUTE_SHOW_NBIO (use nbioLogLib buffering)
■ INCLUDE_NET_ROUTE_SHOW_UNBUF (use printf( ), no buffering)
The default is to use snprintf( ) buffering.
If you are configuring your network stack using Workbench,
SELECT_NET_ROUTE_SHOW_SNPRINTF provides a selection that you can use to
select one of the buffering (or no buffering) options. The selections are:
Network route show snprintf buffering
Sets INCLUDE_NET_ROUTE_SHOW_SNPRINTF, the default.
Network route show nbioLogLib buffering
Sets INCLUDE_NET_ROUTE_SHOW_NBIO.

2. One takes the splnet semaphore by calling splnet( ).

325
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Network route show routines with no buffering (printf)


Sets INCLUDE_NET_ROUTE_SHOW_UNBUF.
If you select INCLUDE_NET_ROUTE_SHOW_SNPRINTF, you have access to the
following parameter:

ROUTE_SHOW_MEM

Synopsis: Preallocated routeShow( ) buffer memory, in bytes. Minimum 256.


Default: 4096

The default buffer size supports about 50 route entries. If, at run-time, you find
that the ROUTE_SHOW_MEM value configured at build time is too small to
buffer the output for the whole routing table, you can increase the global
(integer) variable routeShowMem. If you do this, the next time you call
routeShow( ), mRouteShow( ), or arpShow( ), the old buffer (if any) is freed,
and a new buffer the size of the new value of routeShowMem is allocated. You
can also use this method to decrease the size of the buffer.

16.4 Working with RIP


The purpose of the Routing Information Protocol (RIP) is to maintain routing
information within small inter-networks. RIP is restricted to networks in which the
largest number of hops is 15. Although 15 hops can encompass a very large
network, many networks already exceed this limit.3
The Wind River Network Stack includes implementations of both RIP (version 2,
RFC 2453) and RIPng for IPv6 (RFC 2080). You can use RIP or RIPng as an Interior
Gateway Protocol. Such protocols maintain routing information within small
inter-networks.
The RIP router provided with the Wind River Network Stack is based on the 4.4
BSD routed program. There are several relevant RFCs; the two most important are
RFC 1058, in which RIP version 1 was first documented, and RFC 1388, in which
the version 2 extensions are documented.

3. A packet takes a hop every time it crosses a subnet. If a packet leaves machine Q and must
pass through two subnet routers before it reaches its destination on machine N, the number
of hops is two.

326
16 Adding Routing Support
16.4 Working with RIP

The RIP router supports three modes of operation: Version 1 RIP, Version 2 RIP
with multicasting, and Version 2 RIP with broadcasting.
Version 1 RIP
This mode of operation follows RFC 1058. It uses subnet broadcasting to
communicate with other routers and sends out only a gateway and metric for
each subnet.
Version 2 RIP with Multicasting
In this mode, the router not only knows about other routers but can also
describe routes based on their subnet mask and can designate a gateway that
is not the router that sends the updates. Thus, the machine that hosts the RIP
router does not necessarily have to be the gateway. Because this mode uses
multicasting to communicate, only interested nodes in the network see routing
information and updates.
Version 2 RIP with Broadcasting
This mode is the same as Version 2 RIP with multicasting, except that it uses
broadcasting instead of multicasting. This mode is backwards compatible with
RIP version 1 and is the mode recommended in RFC 1388.
The RIP implementation also supports an interface exclusion list that you can use
to exclude RIP from specific interfaces as they are brought online.

16.4.1 Configuring VxWorks for RIP 16

The INCLUDE_RIP component supplies ripLib and other software modules that
implement the Routing Information Protocol (RIP) for the Wind River
Network Stack. Including INCLUDE_RIP in a VxWorks image sets up a call to the
usrNetRipInit( ) initialization routine, which is defined in the
net/coreip/apps/usrNetRipCfg.c file.
The externally callable API associated with this configuration component is
provided in ripLib. For more information on this API, see the ripLib reference
entry.

! CAUTION: The RIP router does not support separate routing domains. Only
routing domain 0, the default, is supported.

327
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Configuration Parameters

The INCLUDE_RIP component supplies the following configuration parameters:

RIP_EXPIRE_TIME

Synopsis: The maximum time until a route is invalidated.


Default: 180
RIP_EXPIRE_TIME tells RIP the number of seconds between updates before a
route is invalidated. An invalidated route is not used, but it is not necessarily
deleted immediately. Instead, it is retained on what is known as a garbage list.
If confirmation arrives while a route is on the garbage list, the route is marked
as valid. By default, the route remains on the garbage list for a maximum of
120 seconds. You can use RIP_EXPIRE_TIME to lengthen or shorten this time.

RIP_GARBAGE_TIME

Synopsis: The maximum time for which an unconfirmed route is retained.


Default: 300
RIP_GARBAGE_TIME tells RIP the number of seconds to wait before an
unconfirmed route is deleted entirely. This time includes RIP_EXPIRE_TIME.
Thus, the maximum time that a route can remain on the garbage list is the
RIP_GARBAGE_TIME minus the RIP_EXPIRE_TIME. By default, the maximum
time that a route can remain on the garbage list is 120 seconds (300 minus 180).

RIP_GATEWAY

Synopsis: Is this device a gateway to hosts external to the routing domain?


Default: FALSE

! WARNING: Do not set RIP_GATEWAY to TRUE unless this really is the general
gateway. Setting RIP_GATEWAY to TRUE configures the RIP router to ignore any
advertisements for default routers received from other RIP peers.

RIP_MULTICAST

Synopsis: Is multicasting instead of broadcasting enabled for RIP?


Default: FALSE
RIP_MULTICAST tells the router whether it should use the RIP multicast
address (224.0.0.9) instead of using broadcasts. This mode lowers the load on
the network generated by the routing updates. This feature is supported for
VxWorks RIPv2 implementation but not for VxWorks RIPv1 implementation.

328
16 Adding Routing Support
16.4 Working with RIP

In addition, not all RIP routers necessarily support multicasting. For example,
the BSD and SunOS routed implementations do not support multicasting.

RIP_SUPPLIER

Synopsis: Transmit routes regardless of the number of interfaces?


Default: FALSE
When set to TRUE, the RIP_SUPPLIER parameter tells the RIP router to send
out routing information and updates no matter how many physical interfaces
are attached to it. Setting this constant to FALSE turns this feature off.

RIP_SUPPLY_INTERVAL

Synopsis: The time, in seconds, between sending updates.


Default: 30
RIP_SUPPLY_INTERVAL tells RIP how frequently it should transmit route
updates over every known interface. This value must be set to a multiple of the
RIP Timer Rate.

RIP_TIMER_RATE

Synopsis: The number of seconds between state checks.


Default: 1
RIP_TIMER_RATE tells RIP how often it should examine its route cache for 16
changes and expired routes.

RIP_VERSION

Synopsis: The version of the RIP packets processed by this router.


Default: 1
Set to 1, RIP_VERSION tells the router to run just as a version 1 RIP router (as
described in RFC 1058). Such a router ignores all version 2 packets as well as
malformed version 1 packets. Set this constant to 2 to tell the router that it
should send out version 2 packets and that it should listen for and process both
version 1 and version 2 packets. Setting this constant to 2 and the RIP Multicast
Flag, RIP_MULTICAST, to 1, puts the router in full version 2 mode.

RIP_AUTH_TYPE

Synopsis: Tells RIP which authentication method (if any) to use.


Default: 1 (no authentication)

329
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Valid values for RIP_AUTH_TYPE are:


1 – no authentication
2 – simple password authentication
3 – MD5 authentication
The authentication type values of one (1) and two (2) are supported for both
RIP versions. However, MD5 authentication requires RIP version 2. Thus, you
must not combine MD5 authentication with RIP version 1. This combination
forces RIP to ignore all incoming RIP packets.

Run-time Configuration

In addition to setting the defines shown above, there are two alternate methods
you can use to configure RIP:
■ Use the m2Rip routines to configure RIP. These routines are documented in
the reference entries. The parameters to these routines are described in
RFC 1389.
■ Use an SNMP agent to configure RIP.

16.4.2 Using RIP Debugging Routines

For debugging purposes, the RIP router provides ripRouteShow( ), a routine you
can use to print the router’s internal tables to the console. The printed message
provides the following information:
■ the route being advertised
■ the router that routes the packets
■ a subnet mask
■ the timeout on the route (in seconds)4

the flags value (see Table 16-1)
RIP periodically pushes routing information into the Wind River Network Stack
routing table. Between updates, the two tables can diverge, but updating only
periodically avoids route thrashing (pushing transient routes into the system route
table but then removing them immediately).

4. The timeout is the length of time for which the route remains current. If a route is not
updated within 3 minutes, it is flushed from the routing table.

330
16 Adding Routing Support
16.4 Working with RIP

Table 16-1 Flag Constants for ripRouteShow( )

Constant Definition

c Route has changed within the last RIP_SUPPLY_INTERVAL seconds.

e Route should not propagate to other routers.

I Route is internal, used to implement border gateway filtering.

p Route is on a passive interface (loopback).

i Route is on a directly connected interface.

r Route is on a point-to-point link.

s Route is to a subnet (not a host).

o Route belongs to some other (non-RIP) protocol.

p Route is a primary route. If this flag is set, the o flag must also be set.

D Route passes though an interface that is currently down

NOTE: If you exclude RIP, but include SNMP, you might want to edit
snmpMib2.mib to exclude RIP MIB objects. Including these objects does no harm, 16
but it makes the image unnecessarily larger.

16.4.3 Creating an Interface Exclusion List for RIP

By default, RIP runs on all interfaces active when RIP is initialized. If you do not
want to run RIP on a particular interface, you can specify the interface on a RIP
exclusion list. To manage an interface exclusion list, ripLib provides the following
routines:
■ ripIfExcludeListAdd( ) – add an interface to the RIP exclusion list
■ ripIfExcludeListDelete( ) – remove an interface from the RIP exclusion list
■ ripIfExcludeListShow( ) – show the interfaces on the RIP exclusion list
■ ripIfAddrExcludeListAdd( ) – add an interface to the RIP exclusion list
■ ripIfAddrExcludeListDelete( ) – delete an interface from the RIP exclusion list
■ ripIfAddrReset( ) – alter the RIP configuration after an interface changes
■ ripIfReset( ) – alter the RIP configuration after an interface changes

331
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The first three routines identify the interface by name. The next set specify
interfaces by IP address and netmask values. The final routine, ripIfReset( ),
updates the interface list and routing table for the interface specified. For more
information on these routines, see the relevant ripLib reference entries.

NOTE: If RIP is already running on an interface, simply putting an interface on the


exclusion list does not automatically shut down RIP on that interface. To inform
RIP of the new status, you must call ripIfReset( ). Calling ripIfReset( ) clears the
RIP settings for the interface. This means you lose the interface hooks, the interface
MIB-II settings, and all other such information associated with the interface. If you
need to stop RIP over an interface but do not want to clear the RIP interface
settings, you can set the RIP M2 state to invalid. Consider the following code
fragment:
/*
* Next, check the status from the MIB-II RIP group. If this
* interface has been turned off then silently drop packets on it.
*/

if (pIfp->ifConf.rip2IfConfStatus != M2_rip2IfConfStatus_valid)
return (ERROR);

Stopping RIP on an interface this way does not require that you put the interface
on the exclusion list.

RIP and Interface Status Changes

In previous implementations, RIP required you to execute ripIfReset( ) in order to


inform it of the creation or removal of an interface. Because the current RIP
implementation relies upon routing sockets, it detects the interface status change
and adds the new interface (or removes the old interface) automatically, unless the
interface is already named in the RIP interface exclusion list.
The Wind River Network Stack RIP implementation still supports ripIfReset( ),
but keep in mind that a call to ripIfReset( ) clears the RIP interface settings for the
interface. This means you lose the interface hooks, the interface MIB-II settings,
and other such information associated with the interface.

Responding to Route Table Changes by non-RIP Agents

By design, RIP is interested in only those routes that it created or that were
propagated by a RIP peer. Because the current RIP implementation monitors
routing table events using a routing socket, RIP now receives routing socket

332
16 Adding Routing Support
16.4 Working with RIP

messages when other agents (such as OSPF or the system manager) make changes
to the routing table.
By default, RIP still ignores these events. If you want RIP to respond to these
events, use ripRouteHookAdd( ) to register a policy filter to handle these events
for purposes such as propagating static routes or routes from other protocols. The
callback that you register must be of the following form:
STATUS xxripRouteHookRtn
(
struct ROUTE_INFO * pRouteInfo,
int protoId,
BOOL primaryRoute,
int flags
)

RIP invokes this routine in response to the following events:


■ a route was added by an agent other than RIP
(excluding the interface routes the stack creates internally)
■ a route change message arrived
■ an ICMP redirect message arrived
The returned function value of the route hook routine tells RIP how to respond to
the event. In the first case, the returned function value tells RIP whether to add or
ignore the new route. In the second case, the returned function tells RIP whether
to delete the specified route or change its metric. In the third case, the event could 16
indicate an incorrect route entry.
pRouteInfo
This parameter passes in a pointer to a route information structure that stores
the routing message. Do not access the contents of this structure directly.
Instead, use ripAddrsXtract( ) to extract the following information:
■ destination address
■ netmask

gateway address

old gateway address (if available)
The addresses obtained from ripAddrsXtract( ) are valid while this hook
routine is running but not after control returns from the routine. Thus, do not
try to access these address pointers outside the context of the hook routine.
protoId
This parameter passes in the ID of the protocol that generated the event. Valid
protocol IDs are defined in m2Lib.h as follows:

333
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

M2_ipRouteProto_other (static routes)


M2_ipRouteProto_local (system routes, RIP should never see this protoId)
M2_ipRouteProto_netmgmt
M2_ipRouteProto_icmp
M2_ipRouteProto_egp
M2_ipRouteProto_ggp
M2_ipRouteProto_hello
M2_ipRouteProto_rip
M2_ipRouteProto_is_is
M2_ipRouteProto_es_is
M2_ipRouteProto_ciscoIgrp
M2_ipRouteProto_bbnSpfIgp
M2_ipRouteProto_ospf
M2_ipRouteProto_bgp
primaryRoute
This parameter passes in a boolean value that indicates whether the route is a
primary route. TRUE indicates a primary route, the route visible to the IP
forwarding process. FALSE indicates an alternate route to the same
destination.
flags
This parameter passes in a value that indicates which event occurred.
■ 0 indicates a route was added to the routing table by an agent other than
RIP
■ RIP_ROUTE_CHANGE_RECD indicates a route change message
■ RIP_REDIRECT_RECD indicates an ICMP redirect message
These events are described in the following sections.

A New Route was Added to the Routing Table 5

In response to this event, RIP needs to be told whether to ignore or add the route.
RIP does this based on the returned function value of the route hook routine. In the
case of this event, RIP interprets the returned function value of the route hook
routine as the metric for the route.
If the metric is HOPCNT_INFINITY, RIP ignores the route. If the metric is greater
than zero but less than HOPCNT_INFINITY, RIP accepts the route entry. If the route
is new to RIP, RIP adds the new route to its internal database, and then propagates

5. This event does not occur for the route added to the routing table when an interface is
assigned an IP address. Such routes should not be included in the RIP route database. Thus,
RIP never calls the route hook routine when such routes are added to the routing table.

334
16 Adding Routing Support
16.4 Working with RIP

the route in its subsequent update messages. If RIP already stores a route for that
destination, RIP compares the metric of the new route and the stored route. If the
new route has a better (lower) metric, RIP adds the new route. Otherwise, RIP
ignores the new route.
When generating its returned function value, your policy filter can use the creator
of the event (protoID) as a factor in the decision on whether to include the route.
For example, if you wanted the route hook to tell RIP to ignore all routes except
static routes, your route hook would return HOPCNT_INFINITY if the protoID was
anything other than M2_ipRouteProto_other. Routes added to RIP by means of
this policy filter never timeout. They remain in the RIP database until one of the
following events occurs:
■ an agent deletes the route from the system routing table
■ an agent deletes the interface through which the route passes
■ a route change message for the route arrives
In addition, these routes take precedence over RIP routes to the same destination.
RIP ignores routes learned from RIP peers if the policy filter installed a route to the
same destination.

A Route Change Notification Arrived

In response to this event, RIP needs to be told whether to delete the route or change
its metric. If the hook returns a value greater than or equal to HOPCNT_INFINITY,
RIP deletes the route from its internal routing database. If the hook routine returns 16
a valid metric (a value greater than zero but less than HOPCNT_INFINITY), RIP
reassigns the route’s metric to equal the returned value of the route hook routine.
If the returned value of the route hook route is invalid (less than zero) RIP ignores
the event. RIP also ignores the event if the route specified in pRouteInfo is not one
stored in its internal database.

An ICMP Redirect Message Arrived

In response to this event, RIP never needs to make any changes to its internal
routing database. Thus, RIP ignores the returned function value of the route hook
routine called in response to an ICMP redirect message. Because this event may
indicate an incorrect router entry, its execution of the route hook routine allows
you to take appropriate action.
Within your route hook routine, you can recognize an ICMP event by checking
whether the flags parameter value sets the RIP_REDIRECT_RECD bit. The
primaryRoute parameter passes in a boolean value that indicates whether the route
is a primary route.

335
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Removing a RIP Route Hook Routine

Use ripRouteHookDelete( ) to uninstall the RIP hook routine. This causes RIP to
revert to its default behavior of ignoring all routing table events. Any routes
previously installed through any hook routine remain in the internal database.

16.4.4 Writing a Sample Route Hook Callback Routine

As a sample route xxripRouteHookRtn( ) callback, consider the following:


/********************************************************************
*
* ripRouteHook - sample policyfilter- for non-RIP and redirected routes
*
* This routine allows RIP to include static (and other protocol)
* routes in its database and propagate them to its peers.
*
* <pRouteInfo> points to a routing socket message structure that
* describes the route details.
*
* <protoId> identifies that routing protocol that is installing this
* route.
*
* <primaryRoute> indicate if this is the route that will be used
* by the IP forwarding process.
*
* <event> denotes whether this is a ICMP redirected route or a changed
* route or a new route.
*
* event == 0 New route (non-RIP)
* event == RIP_REDIRECT_RECD ICMP redirected route
* event == RIP_ROUTE_CHANGE_RECD Changed route
*
* This routine first extracts pointers to the route destination, netmask and
* gateway from the <pRouteInfo> parameter. In the case of redirects, the old
* gateway address is also extracted and then a log message is printed if
* configured to do so and then this routine exits. If it is a new route,
* this routine asks RIP to reject all routes except the primary routes. For
* static routes, it assigns a metric that is the same as the interface index
* + the interface metric + protocol ID.
*
* RETURNS: A metric value (less than HOPCNT_INFINITY), if the route
* is to be accepted; or HOPCNT_INFINITY, if the route is to be ignored.
*/

STATUS ripRouteHook
(
ROUTE_INFO * pRouteInfo, /* Route information */
int protoId, /* Routing protocol ID */
BOOL primaryRoute, /* Primary route ? */
int event /* Whether redirect */
)

336
16 Adding Routing Support
16.4 Working with RIP

{
int ifIndex;
int metric;
struct sockaddr * pDstAddr, * pNetmask, * pGateway, * pOldGateway;

/* Extract the address pointers from the route info structure */

ripAddrsXtract (pRouteInfo, &pDstAddr, &pNetmask, &pGateway,


&pOldGateway);

/* Get the interface index */

ifIndex = pRouteInfo->rtm.rtm_index;

if (routedDebug)
{
logMsg ("\nripRouteHook:
called for proto: %d, ifIndex=%d, Redirect = %s,"
" Initial metric = %d Primary route=%s\n", protoId, ifIndex,
(int)((event == RIP_REDIRECT_RECD) ? "Yes" : "No"),
pRouteInfo->rtm.rtm_rmx.rmx_hopcount,
(int)(primaryRoute ? "TRUE" : "FALSE"), 0);
ripSockaddrPrint (pDstAddr);
ripSockaddrPrint (pNetmask);
ripSockaddrPrint (pGateway);
}

/* If it is a redirect message, print the old gateway and exit */

if (event == RIP_REDIRECT_RECD)
{
if (routedDebug) 16
{
logMsg ("ripRouteHook:
Redirect received from\n", 0, 0, 0, 0, 0, 0);
ripSockaddrPrint (pOldGateway);
}
return (HOPCNT_INFINITY);
}

/* If it is a route change message, print the old gateway address */

if (event == RIP_ROUTE_CHANGE_RECD)
{
if (routedDebug)
{
logMsg ("ripRouteHook: route change:
Old gateway:\n", 0, 0, 0, 0, 0, 0);
ripSockaddrPrint (pOldGateway);
}
}

/*
* If it is not a primary route return an infinite metric
* to let RIP ignore this route.
*/

337
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

if (! primaryRoute)
return (HOPCNT_INFINITY);

/*
* Calculate metric. We give preference to static routes
* over other routes This is an arbitrary metric which is
* the sum of protocol ID, interface index and the initial
* route metric. Since the static route has the lowest
* protocol ID it gets the lowest metric.
*/

metric = protoId + ifIndex + pRouteInfo->rtm.rtm_rmx.rmx_hopcount;


if (metric >= (HOPCNT_INFINITY - 1))
metric = HOPCNT_INFINITY - 2;

if (routedDebug)
logMsg ("ripRouteHook: returning metric
%d\n", metric, 0, 0, 0, 0, 0);
return (metric);
}

16.5 Adding RIPng Support


The RIPng implementation is similar to RIPv2, but it uses a more flexible address
format that makes it possible to support both IPv4 and IPv6 addresses. To
configure VxWorks for RIPv2 support, add the INCLUDE_RIPNG component.
The INCLUDE_RIPNG component pulls in route6d, a software module that
implements the Routing Information Protocol - Next Generation (RIPng) for IPv6
under VxWorks. Including INCLUDE_RIPNG in a VxWorks image sets up a call to
the usrripngInit( ) initialization routine, which is defined in the
net/coreip/apps/usrNetRipngCfg.c file.
RIPng is similar to RIPv2 but with a more flexible address format that makes it
possible to support both IPv4 and IPv6 addresses. For a detailed description of the
RIPng protocol, see RFC 2080.

NOTE: RIPng does not support the ripRouteHookAdd( ), a RIP (IPv4) utility, that
lets you register a policy filter to notice non-RIP route table events, such as the
addition of a static route or routes from other protocols. Nearly equivalent
functionality and more is built into RIPng and is accessible through the options
you supply in the RIPNG_OPTIONS_STRING string.

338
16 Adding Routing Support
16.5 Adding RIPng Support

To start RIPng, the network initialization code calls ripngStart( ). When called
from the command line, the syntax for ripngStart( ) is as follows:
ripngStart "options", priority
When the initialization code calls this routine, it uses the INCLUDE_RIPNG
component parameters as follows:
ripngStart RIPNG_OPTIONS_STRING, RIPNG_PRIORITY

This component contains the following configuration parameters:

RIPNG_PRIORITY

Synopsis: Specifies the priority of the RIPng daemon task, tRipTask.


Default: 0
In addition to tRipngTask, RIPng also spawns a supporting task, tRipngDog.
The priority for this supporting task is higher than that of tRipTask.
Specifically, it is set to RIPNG_PRIORITY - 1.

RIPNG_OPTIONS_STRING

Synopsis: String containing the options to submit to ripngStart( ).


Default: NULL

Use RIPNG_OPTIONS_STRING to specify RIPng configuration options. If you


want to use an option string, replace the NULL above with a quoted string. For 16
example:
"-s"
The valid options for use within the quoted RIPNG_OPTIONS_STRING string
are as follows:
-a
Enables aging for the statically defined routes. If you specify this option,
RIPng removes even statically defined routes if they have gone too long
without update. The limit is equal to RIP_GARBAGE_TIME plus
RIP_EXPIRE_TIME. By default, that delay would be 480 seconds (300
seconds plus 180 seconds).
-A prefix/prefix_length, interface0 [, interface1, interface2, ... ]
This option is used for aggregating routes. The prefix/prefix_length values
specify the prefix and the prefix length of the aggregated route. When
advertising routes, RIPng filters specific routes covered by the aggregate,
and advertises the aggregated route prefix/prefix_length to the interfaces
specified in the comma-separated interface list interface0 [, interface1,

339
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

interface2, ... ]. To support this behavior, RIPng creates a static route to


prefix/prefix_length with RTF_REJECT flag, in the kernel routing table.
-d
Enables output of debugging messages.
-D
Enables output of extensive debugging messages.
-h
Disable split horizon processing by default. Unless interfaces are explicitly
configured using -x, -y, -z, all new interfaces have Split Horizon with
Poison Reverse enabled. You can use -h to disable this so that all new
interfaces have Split Horizon disabled.
See also -p, which causes all new interfaces to default to Split Horizon
without Poison Reverse. Do not specify -p or -h if you want all new
interfaces to default to Poison Reverse.
-l
Because there is not now a clear definition of the term “site” for IPv6, a
default behavior for RIPng is not to exchange site-local routes. If you
specify the -l option, RIPng assumes all interfaces to be on the same site,
and RIPng will exchange site-local routes with the peers directly accessible
through those interfaces. For this reason, you must not use the -l option if
this RIPng instance is running on a site boundary router.
-L prefix/prefix_length, interface0 [, interface1, interface2, ... ]
Filter incoming routes from interfaces interface0 [, interface1, interface2, ... ].
RIPng will accept incoming routes that are in prefix/prefix_length. If
multiple -L options are specified, any routes that match one of the options
is accepted. A prefix/prefix_length of ::/0 is treated specially as a default
route. For example:
"-L 3ffe::/16,if1 -L ::/0,if1"
This string configures RIPng to accept any default route and any routes in
the 6bone test address, but no others. If you would like to accept any route,
do not specify a -L option.
-N interface0 [, interface1, interface2, ... ]
Do not listen to or advertise routes from/to interfaces specified by
interface0 [, interface1, interface2, ... ].

340
16 Adding Routing Support
16.5 Adding RIPng Support

-O prefix/prefix_length, interface0 [, interface1, interface2, ... ]


Restrict route advertisement to the interfaces specified by interface0
[,interface1, interface2, ... ]. This option also restricts RIPng to advertising
only those routes that matches prefix/prefix_length.
-p
Disable Poison Reverse by default. Including this option configures RIPng
so that all new interfaces to use Split Horizon without Poison Reverse. To
disable Split Horizon entirely, use -h. Note that -p does not affect
interfaces that are explicitly configured using -x, -y, -z. The -p and -h
options are used to set the default mode for only those interfaces that are
not explicitly configured. To use Poison Reverse by default, do not specify
either -p or -h.
-q
Puts RIPng in quiet, listen-only, mode. No advertisements are sent.
-r address1 [,address2, ... ]
Restricted Neighbor List. Accept responses from only those routers
specified in the address list (address1, ...).
-s
Configures RIPng to advertise the statically defined routes stored in the
routing table. Announcements obey the regular split horizon rule.
-S
16
This option is the same as -s option except that no split horizon rule is
applied.
-T interface0 [, interface1, interface2, ... ]
Advertise only default route, toward interface0 [, interface1, interface2, ... ].
-t tag
Attach a route tag to originated route entries. The tag can be decimal
(unprefixed), octal (prefixed by 0), or hexadecimal (prefixed by 0x).
-x interface0 [, interface1, interface2, ... ]
Enable Poison Reverse Processing for these interfaces.
-y interface0 [, interface1, interface2, ... ]
Enable Split Horizon (without Poison Reverse) for these interfaces.
-z interface0 [, interface1, interface2, ... ]
Disable Split Horizon altogether on these interfaces.

341
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

16.6 Adding ARP and NDP Support


The Wind River Network Stack includes an implementation of the Ethernet
Address Resolution Protocol (ARP) as defined by RFC 826. This protocol provides
a mechanism for the resolution of IPv4 addresses to local Ethernet addresses. ARP
depends on the ability to broadcast an ARP request to the local link. Within the
ARP request is the IPv4 address. If a monitoring node on the link owns the IPv4
address specified in the broadcast packet, it responds by sending an ARP response
to the sender. Contained within the ARP response is the responder’s Ethernet
address.
For IPv6, there is no ARP, although the Neighbor Discovery Protocol (NDP), as
defined by RFC 2461, provides equivalent functionality. NDP combines the IPv4
functionality of ARP, ICMP Router Discovery, and ICMP Redirect.

16.6.1 Configuring VxWorks for ARP

The Wind River Network Stack includes two Address Resolution Protocol (ARP)
components.

ARP Management

Including the INCLUDE_ARP_API component pulls in an API for configuring the


ARP protocol for the Wind River Network Stack. Including this component in a
VxWorks image sets up a call to the usrNetArpLibInit( ) initialization routine,
which is defined in the net/coreip/usrNetArpLib.c file.
For information on the externally callable routines associated with this component,
see the arpLib reference entry. This component also pulls in code that can
configure up to five permanent entries in the ARP table at build time.
This component includes five pairs of configuration parameters. Use each
parameter pair to specify a single permanent entry in the ARP table. The string
pairs you supply are used as input for the pHost and pEther parameters to an
arpAdd( ) call. Thus, they must conform to the expectations of arpAdd( ). For more
information on the format of these strings, see the arpAdd( ) reference entry.

ARP_ENTRY_1_HOST

Synopsis: The host name or IP address of the first entry in the ARP table.
Default: NULL, adds no permanent entry to the ARP table.

342
16 Adding Routing Support
16.6 Adding ARP and NDP Support

ARP_ENTRY_1_ADDR

Synopsis: The Ethernet address of the host named in ARP_ENTRY_1_HOST.


Default: NULL, adds no permanent entry to the ARP table.

The flags values used in these arpAdd( ) calls are always ATF_PERM (0x04), a flag
that creates a permanent ARP entry that will not timeout. The default values and
types for the ARP_ENTRY_n_HOST and ARP_ENTRY_n_ADDR parameter pairs are
identical with the pair described above.
ARP_ENTRY_2_HOST – host name or IP address of the second ARP table entry
ARP_ENTRY_2_ADDR – the Ethernet address for ARP_ENTRY_2_HOST
ARP_ENTRY_3_HOST – host name or IP address of the third ARP table entry
ARP_ENTRY_3_ADDR – the Ethernet address for ARP_ENTRY_3_HOST
ARP_ENTRY_4_HOST – host name or IP address of the fourth ARP table entry
ARP_ENTRY_4_ADDR – the Ethernet address for ARP_ENTRY_4_HOST
ARP_ENTRY_5_HOST – host name or IP address of the fifth ARP table entry
ARP_ENTRY_5_ADDR – the Ethernet address for ARP_ENTRY_5_HOST

Proxy ARP Server

The INCLUDE_PROXY_SERVER component pulls in proxyArpLib, a library that


provides an implementation of a proxy Address Resolution Protocol (proxy ARP)
server. Including INCLUDE_PROXY_SERVER in a VxWorks image sets up a call to 16
the usrNetProxyServerInit( ) initialization routine, which is defined in the
net/coreip/usrNetProxyServerCfg.c file.
Using a Proxy ARP server, a VxWorks target can create a logical network that
appears to span physically distinct networks. To do this, Proxy ARP responds to
address resolution protocol (ARP) messages for clients on the subnet for which it
acts as a proxy. The target running the proxy ARP server then updates its route
table so that it can act as an invisible router for the subnet that it manages. From
the perspective of hosts on both the greater network and the subnet, the invisible
routing completely disguises the physical separation of the networks.
This transparency is particularly useful if a VxWorks target is managing a set of
devices that it wants to make available to hosts on a larger network. Using Proxy
ARP, a VxWorks target can safely assign IP addresses from the greater network to
its managed devices. Using ARP, hosts on the greater network can find these
devices that would not otherwise have been directly visible to them.
Without Proxy ARP, the subnet containing the managed devices would require a
distinct network number. Hosts on the greater network could still use normal IP

343
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

routing to access the managed devices on that subnet. This would require an entry
in the route table of each host interested in the managed devices. Proxy ARP lets
you avoid this configuration work.
For more information, see the proxyArpLib reference entries.

Related RFCs

Proxy ARP is described in RFC 925 and an implementation is discussed in RFC


1027. The ARP protocol is described in RFC 826. The implementation of Proxy ARP
for VxWorks is based on RFC 925. It implements only a limited subset of that
proposal.

Parameter Descriptions

The parameters below let you set up a Proxy ARP server that proxies for a single
proxied subnet. Using the API supplied by proxyArpLib, you can configure the
server to handle additional subnets. Thus, a single server can proxy for multiple
subnets. Devices on the proxied subnet must not open interfaces directly onto the
main network. You risk creating network circles and broadcast storms.

PROXYD_MAIN_ADDRESS

Synopsis: The IP address of an existing interface on main network.


Default: sysBootParams.ead
Expects a quoted string containing the IP address of an existing interface on
the main network. The “main” network is the greater network to which you
want to add the nodes that actually reside on a physically distinct subnet.

PROXYD_PROXY_ADDRESS

Synopsis: Proxy ARP Server IP Address (Proxy Network).


Default: sysBootParams.bad
Expects a quoted string containing the IP address of an existing interface on
the subnet for which this server will proxy.

CLNT_TBL_SZ_CFG

Synopsis: Client table size. Interpreted as a power of two.


Default: 8
The client table is implemented using a hash table. The size of that table is
2CLNT_TBL_SZ_CFG elements. Thus, a CLNT_TBL_SZ_CFG of 8 creates a table of
28 elements, which is 256 elements.

344
16 Adding Routing Support
16.6 Adding ARP and NDP Support

PORT_TBL_SZ_CFG

Synopsis: Port table size. Interpreted as a power of two.


Default: 8
The port table is implemented using a hash table. The size of that table is
2PORT_TBL_SZ_CFG elements. Thus, a PORT_TBL_SZ_CFG of 8 creates a table of
28 elements, which is 256 elements.

ARP_DEBUG_CFG

Synopsis: Enable ARP debug messages.


Default: FALSE

PROXY_ARP_VERBOSE_CFG

Synopsis: Enable proxy ARP messages.


Default: FALSE
Configures the server to display debug messages on the console when an ARP
message is forwarded by the proxy server.

PROXY_BROADCAST_VERBOSE_CFG

Synopsis: Enable broadcast messages.


Default: FALSE 16
Configures the server to display debug messages on the console when a
broadcast message is forwarded by the proxy server.

PROXY_BROADCAST_FWD_CFG

Synopsis: Enable broadcast forwarding.


Default: TRUE

ARP_REGISTER_CFG

Synopsis: Use ARP messages to register clients.


Default: TRUE
The default setting is the only valid value for this obsolete parameter. No other
registration methods exist.

345
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

16.6.2 Using NDP

Using NDP, same-link nodes can discover each other’s presence, determine their
respective link-layer addresses, and monitor changes in the addressing or
accessibility of neighbors on the local link. Because the monitoring is active, NDP
can purge cached information that has become invalid. It also lets a host notice
when a router (or the path to a router) fails, which not only lets the host purge the
old route but also triggers a search for a replacement router. This is accomplished
using the following ICMPv6 message types:
Router Solicitation
A host transmits a router solicitation to the local link to discover local routers.
If any IPv6 routers are present, they each respond with a router advertisement.
A host typically initiates a router solicitation through an interface just after
enabling that interface.
Router Advertisement
A router transmits this message to the local link periodically or in response to
a router solicitation. The message contains information such as a prefix that a
host can use for on-link determination, a suggested hop limit value, and the
like. To specify the prefixes that a router advertisement transmits through a
particular interface, use rtadvConfig( ).
Neighbor Solicitation
A node transmits a neighbor solicitation message to determine whether any
local node is using a specific IPv6 address. If a local node is using the address,
it responds with a neighbor advertisement message. A node uses periodic
neighbor solicitations to verify whether a neighbor is still reachable using a
cached link-layer address.
A node also uses neighbor solicitation messages for duplicate address
detection. At boot time, a node constructs a valid link-local IPv6 address for
each of its interfaces. The node may also construct global IPv6 addresses or
acquire them through DHCP. Before using any of these addresses, it sends out
a neighbor solicitation to test that the address is not already in use. Duplicate
address detection is an element of the IPv6 stateless address autoconfiguration
process, which is described in detail in RFC 2462.
Neighbor Advertisement
A node transmits a neighbor advertisement in response to a neighbor
solicitation, if it owns the solicited address. A node can also send an
unsolicited neighbor advertisement to announce a change to its link-layer
address.

346
16 Adding Routing Support
16.7 Using the ICMPv4 Router Discovery Server

Redirect
A router transmits a redirect message to inform hosts of a preferred router to
a destination or to a preferred host.
At build time, the INCLUDE_NDP configuration component supports a
mechanism for adding up to six NDP cache entries. At run-time, you can use
ndp( ) to manage the NDP cache. For more information, see the ndp( ) reference
entry.

16.7 Using the ICMPv4 Router Discovery Server


Using RDISC, a VxWorks target can advertise itself as capable of routing packets
to remote networks. RDISC is somewhat limited in the information that it
provides. As an alternative to RDISC, you should consider using DHCP.
At boot time, the router discovery server sends out an unsolicited advertisement
that identifies it as a router. It repeats this broadcast within an interval whose
maximum and minimum duration is configurable with a call to rdCtl( ).

NOTE: When using rdCtl( ) to adjust the minimum and maximum broadcast
interval, keep in mind that the minimum value must always be lower than that of 16
the maximum. Thus, if you want to change the current maximum to a value less
than that of the current minimum, you must first reduce the minimum to a value
less than the intended maximum. Likewise, if you want to increase the current
minimum to a value greater than the current maximum, you must first increase the
maximum to a value greater than the intended minimum.

Interested hosts on the local network can read the advertisement message and add
that information to their routing table. Interested hosts can also broadcast a router
discovery request message at any time. Hosts that depend on router discovery to
find a router can do this at boot time. In response to a host solicitation, the server
unicasts an advertisement back to the host.

Configuring the VxWorks for the ICMPv4 Router Discovery Server

The INCLUDE_RDISC component pulls in rdiscLib, a library that implements


RDISC, an ICMPv4-based router discovery application. Including
INCLUDE_RDISC in a VxWorks image sets up a call to the usrRdiscInit( )
initialization routine, which is defined in net/coreip/apps/usrNetRdiscCfg.c.

347
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The rdiscLib library does not implement the host side of ICMP router discovery.
A host can solicit for a router at any time simply by multicasting an ICMP router
discovery message to address 224.0.0.2. The format of the solicitation and response
messages is as specified in RFC 1256.

NOTE: As an alternative to ICMP router discovery, consider using DHCP to obtain


the IP addresses of available routers.

Including INCLUDE_RDISC automatically configures the image to call


rdiscLibInit( ) at boot time. Internally, rdiscLibInit( ) spawns tRdisc. As input to
the taskSpawn( ) that launches tRdisc, rdiscLibInit( ) uses the task priority, task
options, and task stack size specified by the following configuration parameters:

RDISC_PRIORITY

Synopsis: Specifies the priority for tRdisc.


Default: 128

RDISC_OPTIONS

Synopsis: Specifies the task options for tRdisc.


Default: 0

RDISC_STACKSIZE

Synopsis: Specifies the stack size for tRdisc.


Default: 20000

Configuring the Router Discovery Server at Run-Time

The rdiscLib functionality includes the control routine rdCtl( ). Using this routine,
you can control the router discovery application and the content of the
advertisements that it transmits.

Application control functionality includes:
– shutting down router discovery entirely
– turning router discovery on or off for a specific interface
– setting an IP address to which advertisements are broadcast
– setting the maximum interval between advertisement transmissions
– setting the minimum interval between advertisement transmissions
– turning debugging messages off or on

Advertisement content control functionality includes:

348
16 Adding Routing Support
16.7 Using the ICMPv4 Router Discovery Server

– advertisement lifetime
– advertisement preference level
For more information, see the rdCtl( ) reference entry.

Responding to Changes in Interface Status

The rdiscLib implementation was written before the network stack included a
registration mechanism for applications interested in interface status events. Thus,
if the Wind River Network Stack host adds or removes an interface after boot time,
the router discovery server will not automatically respond to the change. This can
result in failure to transmit advertisements on the newly started interfaces or in
attempts to transmit advertisements on missing interfaces. To inform rdiscLib of
an interface status changes, call rdiscIfReset( ) immediately after starting or
shutting down an interface.

Shutting Down Router Discovery

To shut down rdiscLib in an orderly fashion, use rdCtl( ).

16

349
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

350
17
Using Fast IP Forwarding

17.1 Introduction 351


17.2 Configuring VxWorks for Fast Path 352
17.3 Launching and Enabling a Fast Path Application 354
17.4 Writing the Initialization Routine for a Fast Path Application 357
17.5 Populating and Maintaining a Fast Path FIB 360
17.6 Managing Your Fast Path Application 361
17.7 Writing Fast Path Application Entry Points 363

17.1 Introduction
A fast IP-forwarding mechanism, also known as a fast path application, intercepts
packets (either IPv4 or IPv6) before they are passed up to IP. If the packet is
destined for a location known to the fast path route cache (also known as the FIB,
the forwarding information base), the application forwards the packet. If the
destination is unknown to the FIB, the application leaves the packet to IP.
This two-level approach lets you bypass regular IP processing for selected packets.
This improves performance on packets headed for destinations known to the FIB.
It reduces performance for all other packets, but overall router performance is
improved if most traffic is headed for destinations known to the FIB. Thus, under

351
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

the right conditions, implementing fast path on a router can result in significant
performance improvements.
In addition to the forwarding mechanism, a fast path application requires a
populated FIB. To support the ability to populate and manage this FIB, the
network stack now supports fastPathLib. This library provides a registration
mechanism for fast path applications interested in the contents of the route table.
The network stack includes a sample fastPathLib application. This sample
application is for demonstration purposes only and is not intended for use as a
deployed fast path application.

The Sample Fast Path Application is Incompatible with Some Services

The sample fast path application supplied in fastPathIp.c is intended as a sample


application. Its main purpose is to show you how to use fastPathLib. Thus, the
application was intentionally kept as simple as possible. It assumes that it can
forward any packet destined for a location known to its route cache. This
assumption works well for simple packets that require no extra processing. That
is, packets that do not require options processing, fragmentation, multicasting,
address translation, and the like.
As shipped, the sample application is incompatible with services such as NAT,
Firewall, and IPSec. If you try to use these services with the sample fast path
application, packets may be mis-routed. If this does not meet your needs, you can
modify the sample application to handle any changes that your require.

Fast Path Applications and Specialized Hardware

The focus of this chapter is on using fastPathLib in a software fast forwarding


application. More significant performance gains can typically be achieved using
specialized hardware.

17.2 Configuring VxWorks for Fast Path


Use the INCLUDE_FASTPATH component to include fastPathLib in a VxWorks
image. This component pulls in fastPathLib and initializes the library. This
component also provides parameters that you can use to set up the launch of a fast
path application. The parameter default values set up and launch an instance of the
sample fast path application.

352
17 Using Fast IP Forwarding
17.2 Configuring VxWorks for Fast Path

The INCLUDE_FASTPATH component contains the following configuration


parameters:

FF_IPV4_INIT_RTN

Synopsis: Fast path IPv4 module initialization routine.


Default: ipFFInit

Use this parameter to specify the initialization routine for an IPv4 fast path
application. Enter a value of -1 if you do not want to initialize an IPv4 fast path
application.

FF_IPV6_INIT_RTN

Synopsis: Fast path IPv6 module initialization routine.


Default: ipFFInit

Use this parameter to specify the initialization routine for an IPv6 fast path
application. Enter a value of -1 if you do not want to initialize an IPv6 fast path
application.

FF_IPV4_FIB_DISP_TBL

Synopsis: IPv4 FIB dispatch table storage method; default is a PATRICIA


tree.
Default: ptRibDispatchTable
Use this parameter to supply the storage method for the FIB used by the 17
sample IPv4 fast path application. A value is required if FF_IPV4_INIT_RTN is
not set to -1.
FF_IPV6_FIB_DISP_TBL

Synopsis: IPv6 FIB dispatch table storage method; default is an AVL tree.
Default: avlRibDispatchTable

Use this parameter to supply a storage method for the FIB used by the sample
IPv6 fast path application. A value is required if FF_IPV6_INIT_RTN is not set
to -1.

353
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

17.3 Launching and Enabling a Fast Path Application


Starting a fast path application does not necessarily start fast forwarding. Whether
the application forwards packets depends on the mode of the application and the
mode of the network interfaces. The system manager can determine and set these
mode values for a registered fast path application using the fastPathLib routines:

ffLibModeSet( ) – start, stop, enable, or disable a fast path application

ffLibModeGet( ) – report the mode of the specified fast path application

ffLibInterfaceModeSet( ) – enable or disable fast forwarding for an interface

ffLibInterfaceModeGet( ) – get the fast forwarding state of an interface
In order for a fastPathLib application to fast forward packets, its mode must be
FF_START and FF_ENABLE. In addition, fast forwarding must be FF_ENABLE on at
least two interfaces (routing implies at least two active interfaces), and forwarding
must be turned on.

17.3.1 Starting a Fast Path Application

There are two ways to start a fast path application. One method uses the
parameters of the ffLibInit( ) routine to launch a fast path application.
Alternatively, you can call the application’s initialization routines directly at a
convenient time after the initial call to ffLibInit( ).
Including the INCLUDE_FASTPATH component in an image sets up an automatic
boot-time call to ffLibInit( ). This routine expects four parameters. The values
passed to this call are configurable at build time using the INCLUDE_FASTPATH
component parameters:
FF_IPV4_INIT_RTN
This parameter expects the initialization routine for an IPv4 fast forwarding
application, or -1 if you do not want to initialize an IPv4 fast path application
at boot time. The default value for this parameter is ipFFInit, the initialization
routine for the sample fast path application.
FF_IPV6_INIT_RTN
This parameter expects the initialization routine for an IPv6 fast forwarding
application, or -1 if you do not want to initialize an IPv6 fast path application
at boot time. The default value for this parameter is ipFFInit, the initialization
routine for the sample fast path application.

354
17 Using Fast IP Forwarding
17.3 Launching and Enabling a Fast Path Application

FF_IPV4_FIB_DISP_TBL
Expects NULL or a pointer to the FIB management routines for the IPv4 fast
path application. The default value for this parameter is ptRibDispatchTable,
which implements a PATRICIA tree FIB.
FF_IPV6_FIB_DISP_TBL
Expects NULL or a pointer to the FIB management routines for the IPv6 fast
path application. The default value for this parameter is
avlRibDispatchTable, which implements an AVL tree FIB. This is the
preferred choice for very large FIBs because, for very large FIBs, an AVL tree
FIB outperforms a PATRICIA tree FIB.
If you use these parameters to launch a fast path application, the system
automatically calls ffLibCachePopulate( ), which populates your application’s
route cache. It also automatically calls ffLibModeSet( ) to set the mode to
FF_START. Setting the mode to FF_START does not start packet forwarding, it just
initializes FIB management for the specified application.
If you set NULL values for the INCLUDE_FASTPATH component parameters, you
must call your application’s initialization routine directly. You also need to handle
the calls to ffLibCachePopulate( ) and ffLibModeSet( ).

17.3.2 Enabling Fast Forwarding

After the application is started, you need to enable fast forwarding on at least two
interfaces and for the application as a whole. 17

To enable fast forwarding on an interface, call


ffLibInterfaceModeSet(..., FF_ENABLE, ... ). You need to do this on at least two
interfaces. Because fast forwarding is packet routing, fast forwarding necessarily
implies at least two network interfaces.
To enable fast forwarding for the application as a whole, call
ffLibModeSet(..., FF_ENABLE, ... ) for the application. Forwarding does not occur
until you set the application mode (not just the interface mode) to FF_ENABLE.
The following is an outline of the steps needed to start fast path.
1. Initialize the fast path application.
There are three ways to do this.
a. Include the INCLUDE_FASTPATH component and set the configuration
parameters to indicate the applications you would like started.

355
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

b. Call ffLibInit( ) manually:


ffLibInit (ipFFInit, ptRibDispatchTable, -1, 0)
/* Initialize fastpath library + Start only the v4 fast forwarder */

c. Call the application initialization routine directly:


ffLibInit (-1, 0, -1, 0) /* Simply initialize the fastpath library */
ffCookie = ipFFInit (0, FF_PROTO_IPV4, ptRibDispatchTable)
/* initialize the v4 fast forwarder */
ffLibModeSet (ffCookie, FF_START) /* Start it */
ffLibCachePopulate (ffCookie) /* Populate its cache */

NOTE: If you use ffLibInit( ) to start the fast path application, it internally
handles the ffLibModeSet( ) and ffLibCachePopulate( ) calls.

2. Enable the fast path application:


ffCookie=ffLibProtoCookieGet (FF_PROTO_IPV4)
/* Get the handle for the IPv4 Fastpath application */
ffLibModeSet (ffCookie, FF_ENABLE) /* Enable it */

3. Enable fast path on at least two interfaces:


ffLibInterfaceModeSet (ffCookie, ifNameToIfIndex ("fei0"), FF_ENABLE)
ffLibInterfaceModeSet (ffCookie, ifNameToIfIndex ("fei1"), FF_ENABLE)

Verify this from the command line. For example:


-> ifconfig "fei0"
fei0: flags=1f8243 mtu 1500
<UP,BROADCAST,RUNNING,ALLMULTI,MULTICAST,NOTRAILERS,INET_UP,INET6_UP,FAST
PATH_V4>
inet6 fe80::21e:a0ff:fe01:2200%motfcc0 prefixlen 64 scopeid 0x2
inet 10.0.0.5 netmask 0xffffff00 broadcast 10.0.0.255
ether 00:1e:a0:01:22:00
value = 0 = 0x0
->

4. Enable IP forwarding:
Sysctl "net.inet.ip.forwarding=1"

The system should now be able to fast forward packets between the two
interfaces. Verify this by calling the ffLibCachePrint( ) to check the status:
-> ffLibCachePrint ffCookie

Wind River's IPv4 Fast Forwarder for protocol IPv4


Fib size: Unlimited
Fast forwarder state: Started (System is making calls)
Enabled (For fast forwarding packets)
IP forwarding is enabled
We are fast forwarding packets
Indirect routes
VC destination/pfx gateway flags Refcnt UseCnt? Iname/Idx
-------------------------------------------------------------------------

356
17 Using Fast IP Forwarding
17.4 Writing the Initialization Routine for a Fast Path Application

vc 10.0.0.0/24 0 0 0 /2
vc 30.0.0.0/24 0 0 0 /3
-------------------------------------------------------------------------

Direct routes
VC destination Gateway MAC Address MTU flags Refcnt UseCnt? Iname/Idx
-------------------------------------------------------------------------
-------------------------------------------------------------------------
value = 0 = 0x0
->

17.4 Writing the Initialization Routine for a Fast Path Application


If you write your own fast path application, you must provide an externally
callable initialization routine for that application. System managers and other
agents can use this routine to launch an instance of your application. Within your
initialization routine, you need to allocate resources for the fast path FIB and
register the application with fastPathLib.

17.4.1 Allocating Resources for the fastPathLib Interface

Within your initialization routine, you need to allocate resources for the interface
17
to fastPathLib. To be compatible with VxWorks configuration utilities, your
externally callable initialization routine should be of the following form:
FF_OBJ * xxInit /* FF_OBJ from internal ffLibObjInit() call. */
(
int numRoutes, /* Maximum number of routes in the FIB. */
int proto, /* Protocol for this FIB, e.g. IP v4. */
FIB_DISPATCH_TBL *pFibDispTbl /* FIB dispatch table. */
)

numRoutes – Limiting the Size of the Fast Path FIB

The numRoutes parameter should limit the number of routes stored in your fast
path FIB. Limiting the number of routes in the FIB can be critical to the efficiency
of the fast path application. The fewer entries there are in the FIB, the faster you
can search the FIB. How you enforce this limit depends on how you implement
your FIB.
Regardless of how you implement your FIB, you must remember that entries are
added to the FIB only when they are added to the route table. Thus, if you remove

357
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

an entry because the FIB is full (and not because the route was deleted from the
route table), the removed route can never make it back into the fast path FIB. In
addition, when you remove an entry to make room, you also must remove all less
specific entries. Otherwise, the less specific entries could be used to incorrectly
forward packets.

proto – Identifying the Protocol

The proto parameter specifies the type of protocol (such as IPv4 or IPv6) for which
the application provides fast forwarding. Currently, there are only two valid
values, FF_PROTO_IPV4 and FF_PROTO_IPV6. This information is needed as part
of the input an application must provide when it registers with fastPathLib.

pFibDispTbl – FIB Management Routines

The pFibDispTbl parameter expects a pointer to an ipRouteDispatchTable


structure. This structure, defined in ipRouteNodeLib.h, provides a set of function
pointers that the fast path application uses to manipulate the contents of its FIB.
Modularizing the FIB management routines this way allows different instances of
the application to use different FIB implementation systems.

NOTE: fastPathLib never interacts directly with the FIB of an application. Thus,
the details of how you reserve and manage storage for your fast path FIB are
entirely up to you. This modularization of the FIB management routines is not
required by fastPathLib, but it was useful in the sample application.

Currently, the network stack supplies two FIB implementations. The FIB
implementation in ptRouteNodeLib.c defines ptRibDispatchTable, a table of
routines that manage a FIB implementation based on a PATRICIA tree. The FIB
supplied in avlRouteNodeLib.c defines avlRibDispatchTable, a table of routines
that manage a FIB implementation based on an AVL tree.

NOTE: The routines supplied in ptRouteNodeLib.c and avlRouteNodeLib.c are


not supported for external use, and could change dramatically between releases.

FF_OBJ – Tracking a Fast Path Application Instance

Within your initialization routine, you must allocate, initialize, and return an
FF_OBJ structure dedicated to your application instance. To initialize this
structure:
1. Zero-out the FF_OBJ structure.
2. Set FF_OBJ.ffVersion to FF_VERSION.

358
17 Using Fast IP Forwarding
17.4 Writing the Initialization Routine for a Fast Path Application

3. Submit the FF_OBJ structure to ffLibObjInit( ).


After initialization, your application uses this FF_OBJ structure to identify itself
when calling fastPathLib routines.

NOTE: Aside from the ffVersion field, never set any FF_OBJ members directly.
Treat the FF_OBJ members as read-only entities.

17.4.2 Registering a Fast Path Application with fastPathLib

To register with fastPathLib, an application must call ffLibObjInit( ):


STATUS ffLibObjInit
(
FF_OBJ *pFFObj, /* Allocated but uninitialized FF_OBJ. */
int numRoutes, /* Max number of routes in FIB. */
int proto, /* Protocol type, IP v4, IP v6, etc. */
char *pIdString, /* Description of this application instance. */
FF_FUNCTIONS *pFFFuncs, /* Entry points for export to fastPathLib. */
void *pPrivateData /* Pointer to private data for application. */
)

The key input to ffLibObjInit( ) is supplied by pFFFfuncs, which expects a pointer


to a fully initialized FF_FUNCTIONS structure. Your application uses this structure
to publicize entry points that fastPathLib can use to inform your application of
events relevant to routing management.
The FF_FUNCTIONS structure is defined in 17
installDir/vxworks-6.n/target/h/wrn/coreip/fastPath/fastPathLib.h as follows:
typedef struct ffFunctions
{
STATUS (* ffShutdown) (FF_OBJ *);
BOOL (* ffPktSend) (FF_OBJ *, struct sockaddr *, M_BLK_ID, USHORT,
void *);
STATUS (* ffRouteAdded) (FF_OBJ *, int, int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, int, void *);
STATUS (* ffRouteDeleted) (FF_OBJ *, int, int, struct sockaddr *,
struct sockaddr *, struct sockaddr *);
STATUS (* ffRouteModified) (FF_OBJ *, int, int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, struct sockaddr *);
STATUS (* ffRouteComplete) (FF_OBJ *, struct sockaddr *,
struct sockaddr *,struct sockaddr *, char *, int, int, int,
int, void *);
STATUS (* ffMacEntryDeleted) (FF_OBJ *, struct sockaddr *,
struct sockaddr *);
STATUS (* ffRouteDemoted) (FF_OBJ *, int, struct sockaddr *,
struct sockaddr *, struct sockaddr *);
STATUS (* ffRoutePromoted) (FF_OBJ *, int, struct sockaddr *,
struct sockaddr *, struct sockaddr *);

359
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

STATUS (* ffInterfaceModeChanged) (FF_OBJ *, int, int);


STATUS (* ffModeChanged) (FF_OBJ *, int);
STATUS (* ffInterfaceStatusChanged) (FF_OBJ *, int, int, void *);
STATUS (* ffFibFlush) (FF_OBJ *);
STATUS (* ffFibWalk) (FF_OBJ *, FF_USER_WALK_FUNC_ID, void *);
} FF_FUNCTIONS;

If your application is not interested in the notification associated with a routine in


FF_FUNCTIONS, your application can set the relevant FF_FUNCTIONS field value
to NULL. The only exception is the ffFibWalk field, for which you must provide a
routine that fastPathLib can call to walk your fast path FIB when it needs to print
or dump the fast path FIB.
For more information concerning the routines referenced in an FF_FUNCTIONS
structure, see 17.7 Writing Fast Path Application Entry Points, p.363.

17.5 Populating and Maintaining a Fast Path FIB


After registering with fastPathLib, your application is ready to populate its
routing FIB.

Populating a Fast Path FIB

Your application or a system manager can call ffLibCachePopulate( ). This routine


triggers a dump of all the routes in the route table. Internally,
ffLibCachePopulate( ) calls your application’s xxRouteAdded( ) exactly once for
each route in the route table. In your xxRouteAdded( ) routine, you should enforce
your policy (if any) concerning which routes are added to the FIB and which are
excluded.
If xxRouteAdded( ), decides to add the route to the table, add the route to your fast
path FIB as an incomplete route entry. The next time a packet needs forwarding
using that route, fast path will need to leave the packet to the slow path system. As
soon as slow path transmits the packet, the event will trigger fastPathLib to call
your ffRouteComplete( ) routine, which will complete the route entry and allow
fast forwarding to that destination for all suitable and subsequent packets.

360
17 Using Fast IP Forwarding
17.6 Managing Your Fast Path Application

NOTE: Before calling ffLibCachePopulate( ), use ffLibModeSet( ) to set the


application mode value to FF_START. This mode lets fastPathLib manage (make
changes to) the specified application. This mode does not turn on fast forwarding.

Maintaining a Fast Path FIB

As routes in the route table are modified, deleted, or added, fastPathLib informs
the relevant registered fast path application of the changes. If the event concerned
an IPv4 route, the registered IPv4 fast path application (if any) is informed of the
event. Likewise, if the event concerned an IPv6 route, the registered IPv6 fast path
application (if any) is informed of the event. fastPathLib supports only one fast
path application per protocol.
When a route is deleted, fastPathLib calls the xxRouteDeleted( ) entry point (see
ffRouteDeleted, p.367) or the xxMacEntryDeleted( ) entry point (see
ffMacEntryDeleted, p.369) from the registered IPv4 or IPv6 application. A changed
route entry generates a call to the xxRouteModified( ) entry point (see
ffRouteModified, p.367).
The addition of a new route results in two different entry point calls. The first is a
call to the xxRouteAdded( ) entry point (see ffRouteAdded, p.366). This provides
information on a route when it is first added to the route table. Because the route
table does not yet have ARP or link layer information for the new route,
fastPathLib cannot supply the xxRouteAdded( ) call with forwarding information
17
(such as the MAC address of the next hop or destination). As soon as the ARP
information is available, fastPathLib supplies it by calling the registered IPv4 or
IPv6 xxRouteComplete( ) entry point (see ffRouteComplete, p.368).

17.6 Managing Your Fast Path Application


As mentioned earlier, your application needs to provide an externally callable
application-launching routine that system managers can use to launch your
application. Internally, this routine must register your application instance with
fastPathLib.

361
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

After registration with fastPathLib, system managers can manage your


application by making calls to the following routines:

ffLibShutDown( ) – shutdown a fast path application

ffLibModeSet( ) – turn forwarding off or on globally

ffLibModeGet( ) – report whether forwarding is off or on globally

ffLibInterfaceModeSet( ) – turn forwarding off or on for an interface

ffLibInterfaceModeGet( ) – report forwarding mode for an interface
■ ffLibCachePopulate( ) – populate a FIB from the route table
■ ffLibCachePrint( ) – print a FIB
■ ffLibCacheDump( ) – dump the FIB contents
■ ffLibCacheFlush( ) – clear all route entries from the FIB
To support these fastPathLib routines, your fast path application must implement
the following entry points:
■ xxShutDown( ) – shut down a fast path application instance
■ xxInterfaceModeChanged( ) – turn forwarding off or on for an interface
■ xxModeChanged( ) – turn forwarding off or on globally
■ xxFibFlush( ) – flush the FIB of all route entries
■ xxFibWalk( ) – apply an input routine to each entry in the FIB
In addition, to respond when an interface is added to or removed from the system,
your fast path application must implement the entry point:
■ xxInterfaceStatusChanged( ) – respond to a change of interface status
Finally, your fast path application should implement an externally callable
xxFibLookup( ) routine. This routine lets you query your fast path application for
a route to a particular IP address. If the fast path FIB contains a matching route, this
routine returns the route information. Otherwise, it returns NULL. No fastPathLib
routine ever calls your xxFibLookup( ) directly, nor is it referenced in the
FF_FUNCTIONS structure. An externally callable xxFibLookup( ) is often useful
when trying to debug your fast path application.

362
17 Using Fast IP Forwarding
17.7 Writing Fast Path Application Entry Points

17.7 Writing Fast Path Application Entry Points


Within your fast path application, you must implement entry points for the
routines referenced within the FF_FUNCTIONS structure used to register the
application with fastPathLib. This structure requires pointers to the following
entry points:

ffShutdown – shut down the fast path application instance

ffPktSend – forward a packet (not required if handled in hardware)

ffRouteAdded – respond to a route add event (route may be incomplete)

ffRouteDeleted – respond to a delete route event

ffRouteModified – respond to a route modified event

ffRouteComplete – respond to completion of a route add event

ffMacEntryDeleted – respond to a MAC entry deletion event

ffRouteDemoted – respond to a route demoted event

ffRoutePromoted – respond to a route promoted event

ffInterfaceModeChanged – respond to a change of mode for an interface

ffModeChanged – respond to a mode change for the fast path application

ffInterfaceStatusChanged – respond to a status change for an interface

ffFibFlush – flush the internal FIB of the fast path application

ffFibWalk – apply a function to each entry in the fast path FIB
You should also implement an xxFibLookup( ) entry point as well as routine that
launches an instance of your fast path application. The following sections describe
the required prototypes for all the routines referenced in an FF_FUNCTIONS
structure. It also includes a description of the routine prototype for your 17
xxFibLookup( ) routine.

NOTE: In the text below, elements such as ffShutDown, ffPktSend,


ffRouteAdded, and so on refer to the members of an FF_FUNCTIONS structure.
Items such as xxShutDown( ), xxPktSend( ), and xxRouteAdded( ) refer to the
routines that you implement and reference in the ffShutDown, ffPktSend, and
ffRouteAdded members of an FF_FUNCTIONS structure.

Avoiding FIB Access Conflicts

To ensure the integrity of the FIB and the application state, fastPathLib takes the
splnet lock whenever it calls an entry point in your fast path application.

363
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Generic Parameter Descriptions

In the following prototype descriptions, you will see the same parameters
appearing repeatedly. Below are generic descriptions of these common
parameters.
pFFObj
A pointer to the FF_OBJ used to register this fast path application instance with
fastPathLib. Never directly modify the members of this structure after it is
initialized in a call to ffLibObjInit( ).
weight
Indicates the weight associated with the route. FF_REP_ROUTE is passed in for
a representative route. Otherwise, this parameter passes in the actual route
weight, a value that is assigned to the route by the agent that creates the route.
pDstAddr
Points to the destination network protocol address.
pNetmask
Points to the destination netmask.
pGateway
Points to the gateway address.
flags
Passes in a value that describes whether the route is a gateway route, a host
route, an interface route, or a point-to-point route. Valid values are:
■ FFF_INDIRECT – indicates an indirect (gateway) route.
■ FFF_HOST – indicates a route to a host.
■ FFF_IF_ROUTE – indicates an interface route.
■ FFF_PTP – indicates a point-to-point interface route.
Although you do not use FFF_IF_ROUTE routes (interface routes) directly to
transmit packets, they do provide valuable information.
Thus, your application does need to store and manage them. Your application
needs to store the information in a way that prevents it from forwarding
packets destined to a local interface. In the sample application, such routes are
stored in the FIB, but they are marked as INCOMPLETE, which prevents
forwarding.
mtuSize
Specifies the MTU size (maximum transfer unit size) of the interface associated
with a route. Use this value to determine whether the packet needs to be

364
17 Using Fast IP Forwarding
17.7 Writing Fast Path Application Entry Points

fragmented before transmission. If the packet needs fragmenting, it should be


left to IP.
ifIndex
Points to the interface index. This value identifies the interface associated with
the route. If your fast path application is notified of a status change for that
interface, it should apply the consequences of the change to all stored routes
through that interface. For example, if the interface is deleted, you typically
want to delete all routes through that interface. If forwarding were disabled
for the interface, you probably want to invalidate but not delete all routes
through that interface.
pIfCookie
Points to a cookie from the interface associated with the route. If you use this
route to transmit a packet, you must update the statistics for the interface
associated with that route. To do this, you must call ffLibUpdateStats( ),
which expects this interface cookie as input. For more information, see the
ffLibUpdateStats( ) reference entry.

ffShutdown

The prototype for this entry point is as follows:


STATUS xxShutDown
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier */
)

fastPathLib calls this entry point in response to an ffLibShutDown( ) call. Within 17


your xxShutDown( ) implementation, you should do whatever it takes to shut
down your fast path application in an orderly manner, which should include
freeing the FIB storage. The fastPathLib already ensures that the application is
stopped and all the FIB entries flushed before calling the xxShutDown( ) routine.

ffPktSend

The prototype for this entry point is as follows:


BOOL xxPktSend
(
FF_OBJ *pFFObj, /* Fast path application identifier object. */
struct sockaddr* pDstIpAddr, /* Final destination of the packet. */
M_BLK_ID pMblk, /* mBlk containing the packet to forward. */
USHORT netType, /* Protocol type: FF_PROTO_IPV4 or FF_PROTO_IPV4. */
void *pIfCookie /* Cookie for an ffLibUpdateStats call. */
)

fastPathLib calls your xxPktSend( ) routine whenever a packet is received from a


network interface. If you implement forwarding in hardware, set the ffPktSend

365
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

field of your FF_FUNCTIONS structure to NULL before calling ffLibObjInit( ).


Otherwise, the ffPktSend field should reference your xxPktSend( ) entry point.
Your xxPktSend( ) entry point must determine whether the packet in pMblk is
suitable for forwarding and then forward the packet if appropriate, which the
sample application defines according to the following criteria:

not needing IP option processing
■ not needing fragmentation
■ headed to some place for which the FIB contains a usable route
To check for the first two criteria, you can inspect the packet. To check the
destination address in pDstIpAddr against your FIB, call your xxFibLookup( ) entry
point. If your FIB supplies a usable route, you can forward the packet, call
ffLibUpdateStats( ), and return.
To indicate that it forwarded the packet, your xxPktSend( ) should return TRUE.
For packets it cannot forward, your xxPktSend( ) should return FALSE, which tells
fastPathLib that it should pass the packet up to IP for normal processing.

NOTE: If your xxPktSend( ) forwards a packet, it is critical that your xxPktSend( )


call ffLibUpdateStats( ).

ffRouteAdded

The prototype for this entry point is as follows:


STATUS xxRouteAdded
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int weight, /* Route weight. */
int flags, /* route: indirect, host, interface, p-to-p.*/
struct sockaddr *pDstAddr, /* Destination Address. */
struct sockaddr *pNetmask, /* Network mask (IPv4) or prefix (IPv6). */
struct sockaddr *pGateway, /* Gateway address. */
int mtuSize, /* Maximum Transfer Unit size for device. */
int ifIndex, /* Index of interface. */
void *pOutIfCookie /* Interface output cookie. */
)

fastPathLib calls your xxRouteAdded( ) routine to tell your fast path application
that a route has just been added to the route table. fastPathLib also calls
xxRouteAdded( ) to respond to an ffLibCachePopulate( ) call.
When fastPathLib uses your xxRouteAdded( ) to report that a route has just been
added to the route table, the route description is necessarily incomplete, unless the
route is though a non-MAC interface, such as a PPP interface. This is because
fastPathLib calls your xxRouteAdded( ) before the route table has received the

366
17 Using Fast IP Forwarding
17.7 Writing Fast Path Application Entry Points

ARP information for the route. When the ARP information arrives, fastPathLib
calls your xxRouteComplete( ) to pass the information along to your fast path
application.
When fastPathLib calls your xxRouteAdded( ) as part of its response to a
ffLibCachePopulate( ) call, it calls it for each route in the slow path route table.
The routes that you create for these calls must all be incomplete, except for routes
through the non-MAC interface. The next time slow path transmits a packet over
one of these routes, fastPathLib will call your xxRouteComplete( ) to supply the
information needed to complete the route entry.

NOTE: It is within xxRouteAdded( ) that your fast path application must enforce a
filter policy that determines which routes are stored and which are ignored.

ffRouteDeleted

The prototype for this entry point is as follows:


STATUS xxRouteDeleted
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int flags, /* route: indirect, host, interface, p-to-p.*/
struct sockaddr *pDstAddr, /* Destination Address. */
struct sockaddr *pNetmask, /* Network mask (IPv4) or prefix (IPv6). */
struct sockaddr *pGateway, /* Gateway address. */
)

fastPathLib calls your xxRouteDeleted( ) routine to tell your fast path application
that a route has been deleted from the route table. Within this routine, your fast 17
path application should delete the specified route from your fast path FIB if it is
present. Failure to find the route in your FIB does not necessarily indicate a
problem. Depending on the filtering policy you implement (if any), you might not
have stored the route when fastPathLib informed you of its creation.

ffRouteModified

The prototype for this entry point is as follows:


STATUS xxRouteModified
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int weight, /* Route weight. */
int flags, /* route: indirect, host, interface, p-to-p.*/
struct sockaddr *pDstAddr, /* Destination Address. */
struct sockaddr *pNetmask, /* Network mask (IPv4) or prefix (IPv6). */
struct sockaddr *pGateway, /* Gateway address. */
struct sockaddr *pOldGateway, /* Old gateway address. */
)

367
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

fastPathLib calls your xxRouteModified( ) to tell your fast path application that
the described route has changed.

ffRouteComplete

The prototype for this entry point is as follows:


STATUS xxRouteComplete
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
struct sockaddr *pDstAddr, /* Destination Address. */
struct sockaddr *pNetmask, /* Network mask (IPv4) or prefix (IPv6). */
struct sockaddr *pGateway, /* Gateway address. */
char *pDstMacAddr, /* MAC Address. */
int macAddrLen, /* MAC Address Length. */
int flags, /* route: indirect, host, interface, p-to-p.*/
int mtuSize, /* Maximum Transfer Unit size for device. */
int ifIndex, /* Index of interface. */
void *pOutIfCookie /* Interface output cookie. */
)
pDstMacAddr
The MAC address for the next destination. If the ultimate destination is local
to the subnet (flags is not FFF_INDIRECT), this is the MAC address of the IP
address specified in pDstIpAddr. Otherwise, this parameter passes in the MAC
address for the gateway machine specified in pGateway. This pointer is NULL if
the route is over a point-to-point connection.
macAddrLen
Specifies the length of the MAC address referenced in pDstMacAddr. A
macAddrLen value of zero tells you that this route passes through a
point-to-point connection and that pDstMacAddr should be ignored.
fastPathLib calls your xxRouteComplete( ) to supply your fast path application
with the ARP information needed to complete the information supplied in a prior
xxRouteAdded( ) call.
If you are selective about which routes you add to your fast path FIB, the previous
xxRouteAdded( ) may not have stored the route. In that case, your
xxRouteComplete( ) should be able to ignore the supplemental information for the
previously ignored route.
Your xxRouteComplete( ) also needs to be able to ignore calls made against
already completed FIB entries. These extra calls arise whenever the slow path
system transmits a packet that your fast path application could have forwarded
(based on its destination) but did not forward because it was unsuitable for
forwarding (because it was fragmented, or required options processing, or failed
to meet some other criteria important to your application).

368
17 Using Fast IP Forwarding
17.7 Writing Fast Path Application Entry Points

In the sample application, the xxRouteAdded( ) routine creates an incomplete


route in the fast path FIB. When fastPathLib later calls your xxRouteComplete( )
to supply the missing ARP information, the sample application completes the FIB
entry.

ffMacEntryDeleted

The prototype for this entry point is as follows:


STATUS xxMACEntryDeleted
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
struct sockaddr *pGateIpAddr, /* Gateway IP address. */
struct sockaddr *pGateMacAddr /* Gateway MAC address. */
)
pGateIpAddr
IP address of gateway machine formerly accessible using the MAC address in
pGateMacAddr.
pGateMacAddr
MAC address now considered invalid.
fastPathLib calls your xxMacEntryDeleted( ) when a MAC address is no longer
valid and has been deleted from the route table. Your xxMacEntryDeleted( ) must
remove or invalidate any FIB entry that stores or references the deleted MAC
address.

ffRouteDemoted
17
The prototype for this entry point is as follows:
STATUS xxRouteDemoted
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int flags, /* route: indirect, host, interface, p-to-p.*/
struct sockaddr *pDstAddr, /* Destination Address. */
struct sockaddr *pNetmask, /* Network mask (IPv4) or prefix (IPv6). */
struct sockaddr *pGateway, /* Gateway address. */
)

fastPathLib calls your xxRouteDemoted( ) to tell your fast path application that
the described route has been demoted. A demoted route should not be used for IP
forwarding.

369
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

ffRoutePromoted

The prototype for this entry point is as follows:


STATUS xxRoutePromoted
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier */
int flags, /* route: indirect, host, interface, p-to-p */
struct sockaddr *pDstAddr, /* Destination Address. */
struct sockaddr *pNetmask, /* Network mask (IPv4) or prefix (IPv6) */
struct sockaddr *pGateway, /* Gateway address. */
)

fastPathLib calls your xxRouteDemoted( ) to tell your fast path application that
the described route has been promoted. A promoted route should be used for IP
forwarding instead of the previously representative route for the destination.

ffInterfaceModeChanged

The prototype for this entry point is as follows:


STATUS xxInterfaceModeChanged
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int ifIndex, /* Index of interface. */
int mode /* New interface mode: FF_ENABLE, FF_DISABLE. */
)
mode
Tells xxInterfaceModeChanged( ) whether it should enable or disable fast
forwarding for a particular interface. This parameter takes one of two values:
FF_ENABLE
Enable fast forwarding for the interface specified in ifIndex.
FF_DISABLE
Disable fast forwarding for the interface specified in ifIndex.
fastPathLib calls your xxInterfaceModeChanged( ) when an agent, such as a
system administrator, has used ffLibInterfaceModeSet( ) to enable or disable fast
forwarding for the interface specified by ifIndex.

NOTE: In a hardware-based forwarder, make sure that you forward packets only
if the system manager has enabled forwarding for both the application and the
interface. For a software based forwarder, this is handled for you. In a software
forwarder, the system will not call the ffPktSend( ) routine unless forwarding is
enabled for both the application and the interfaces.

370
17 Using Fast IP Forwarding
17.7 Writing Fast Path Application Entry Points

ffModeChanged

The prototype for this entry point is as follows:


STATUS xxModeChanged
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int mode /* New application mode: FF_ENABLE, FF_DISABLE. */
)
mode
Tells xxModeChanged( ) whether it should enable or disable fast forwarding
for this fast path application instance. This routine is a global (all interfaces)
version of your xxInterfaceModeChanged( ). This parameter supplies one of
two values:
FF_ENABLE
Enable fast forwarding for this fast path application instance.
FF_DISABLE
Disable fast forwarding for this fast path application instance. Within a
hardware-based forwarding application, do whatever is necessary to
guarantee that your hardware does not forward packets. For a
software-based forwarder, the system does not call ffPktSend( ) if
forwarding has been disabled.
fastPathLib calls your xxModeChanged( ) when an agent, such as a system
administrator, has used ffLibModeSet( ) to enable or disable fast forwarding for
all interfaces associated with this fast forwarding instance.
17
ffInterfaceStatusChanged

The prototype for this entry point is as follows:


STATUS xxInterfaceStatusChanged
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
int ifIndex, /* Index of interface. */
int status /* New interface status. */
void *pArg /* Address to add or delete if the change requires it. */
)
status
Passes in a value that indicates the status of the interface specified in ifIndex.
FF_IFADDR_ADD
An address has been added to the interface. The address is identified in the
ffIfAddrArg structure referenced in pArg. This notice is for the sake of
completeness. No response is required of your application.

371
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

FF_IFADDR_DELETE
An address has been deleted from the interface. The address is identified
in the ffIfAddrArg structure referenced in pArg. Applications should
typically delete routes passing through the affected virtual interface. Note
that for a single physical interface, there can be many virtual interfaces,
each designated by its own ifaddr.
FF_IF_DELETE
The interface has been deleted. Your fast path application should flush all
routes going through this interface. For this value, pArg is always NULL.
FF_IF_ADD
The interface has been added.
FF_IF_UP
The interface has been brought up. Consider revalidating any FIB entries
associated with this interface.
FF_IF_DOWN
The interface has been brought down. Consider invalidating any FIB
entries associated with this interface.
pArg
If status is either FF_IFADDR_ADD or FF_IFADDR_DELETE, this parameter
passes in a pointer to an ffIfAddrArg structure that contains the address
added to or deleted from the interface identified in ifIndex. The ffIfAddrArg
structure is defined as follows:
struct ffIfAddrArg /* Defined in fastPathLib.h. */
{
struct sockaddr * pIfaAddr; /* Interface address. */
struct sockaddr * pIfaNetmask; /* Interface netmask or prefix. */
};

fastPathLib calls this routine to notify the application of an interface being added
or deleted, or of an address being added to or deleted from that interface.

ffFibFlush

The prototype for this entry point is as follows:


STATUS xxFibFlush
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
)

fastPathLib calls this entry point when some agent has called ffLibCacheFlush( ).
Internally, your xxFibFlush( ) should do whatever is necessary to clear all route
entries currently stored in the fast path FIB.

372
17 Using Fast IP Forwarding
17.7 Writing Fast Path Application Entry Points

ffFibWalk

The prototype for this entry point is as follows:


void xxFibWalk
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier. */
FF_USER_WALK_FUNC_ID pUserFunc, /* Function run on each FIB entry. */
void *userArg /* Arguments to pass to pUserFunc. */
)
userFunc
Passes in a FF_USER_WALK_FUNC_ID, which is a function pointer defined as
follows:
typedef STATUS (* FF_USER_WALK_FUNC_ID) (FF_PUB_FIB_ENTRY *, void *);

Your xxFibWalk( ) implementation must call this routine for each route in
your FIB and then return when it reaches the end of the FIB. For the first
parameter, pass in a FIB entry using a FF_PUB_FIB_ENTRY structure, which is
defined as:
typedef struct ffPubFibEntry
{
SOCKADDR_STORAGE_T dstAddr;
SOCKADDR_STORAGE_T netmask;
SOCKADDR_STORAGE_T gateAddr;
struct sockaddr_dl macAddr;
unsigned int routeMetric;
unsigned int ifMtu;
unsigned int ifIndex;
unsigned int useCount;
unsigned int refCount; 17
unsigned int flags;
void * pOutIfCookie;
} FF_PUB_FIB_ENTRY;

For the second parameter, pass in userArg.


If the pUserFunc call returns any value other than zero, your xxFibWalk( )
should stop its FIB walk and return immediately.
userArg
Passes in a pointer that you should pass into userFunc as the second parameter.
fastPathLib calls this routine when it must apply a routine (such as print or dump)
to every entry in your FIB.

373
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

xxFibLookup

The prototype for this entry point is as follows:


STATUS xxFibLookup
(
FF_OBJ *pFFObj, /* Fast Path Application Identifier */
struct sockaddr *pDstAddr, /* Destination Address. */
FF_PUB_FIB_ENTRY * pPubFibEntry /* Out parameter for FIB match. */
)
pDstIpAddr
The IP address for which to search your FIB.
pPubFibEntry
If your xxFibLookup( ) can find a route in its FIB that matches the IP address
specified in pDstIpAddr, it should use this out parameter to return that
information formatted as an FF_PUB_FIB_ENTRY structure (see
installDir/vxworks-6.n/target/h/wrn/fastPath/fastPathLib.h). Otherwise,
pPubFibEntry should return NULL.
fastPathLib never calls your xxFibLookup( ) directly. Thus, you do not need to
conform strictly to the API shown above. You will need to implement this routine
for the internal needs of you application (your xxPktSend( ) will need to call such
a routine). In addition, you should implement your xxFibLookup( ) as an
externally callable routine. It is a useful thing to have when debugging.

374
18
Adding IGMP, MLD, and
Multicast Routing Support

18.1 Introduction 375


18.2 Adding IGMP Host and Router Support 378
18.3 Controlling Multicast Routing 382
18.4 Adding and Deleting Virtual Interfaces for Multicast Routing 383
18.5 Using the Advanced Multicast Routing API 385
18.6 Using PIM 392
18.7 Configuring and Using MLD Hosts and Routers 394

18.1 Introduction
The Wind River Network Stack implements IGMP and MLD to support
multicasting in the IPv4 and IPv6 domains.
In support of multicasting in the IPv4 domain, the Wind River Network Stack
implements the Internet Group Management Protocol (IGMP). An IGMPv2 host is
available to all builds of the network stack. The IGMPv3 host and the IGMPv2
router are only available in the Wind River Platforms builds. There is no router
implementation for IGMPv3 in any build of the network stack.
In support of multicasting in the IPv6 domain, the Wind River Network Stack
implements the Multicast Listener Discovery (MLD) protocol. An MLDv1 host is

375
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

available to all builds of the network stack. The MLDv2 host and MLDv2 router
implementations are only available in the Wind River Platforms.
Currently, Wind River does not supply a PIM implementation. Consequently, the
MLDv2 router implementation cannot act as a true MLDv2 router, but it can act as
a relay agent that proxies for a PIM-coupled MLDv2 router. However, because the
network stack does include the socket mechanisms required for accessing
multicasting functionality, you can port a PIM implementation (or an equivalent)
if necessary.

NOTE: The IGMPv2 router, the IGMPv3 host, and the MLDv2 protocols are
available only in the Wind River Platforms builds of the network stack. The Wind
River General Purpose Platform, VxWorks Edition, does not support these
features

IP Addressing

Both IGMP and MLD define a set of control messages that IP hosts can use to
inform routers of their interest in joining or leaving a multicast group. Hosts may
join or leave multicast groups freely and at any time.
Associated with each multicast group is a specific IP address. Any host that wants
to send data to the members of a multicast group need only transmit to the
appropriate multicast IP address. Hosts that want to transmit multicast data need
not be members of the multicast group to which they transmit. When an IP stack
on a router receives a packet with a multicast group destination address, the router
forwards the packet to any hosts that have registered with it for that multicast
group. Thus, although any host can transmit to a multicast group, only registered
group members receive the multicast.

IPv4

Under IPv4, multicast group addresses are restricted to the class D addresses,
which range from 224.0.0.0 to 239.255.255.255. Within this range, certain addresses
and address ranges are already registered to specific uses and protocols. For
example, 224.0.0.1 multicasts to all systems on the local subnet. The Internet
Assigned Numbers Authority (IANA) maintains a list of registered IPv4 multicast
groups. As described in RFC 3232, this list is now published online at:
http://www.iana.org/assignments/multicast-addresses
This online list obsoletes RFC 1700.

376
18 Adding IGMP, MLD, and Multicast Routing Support
18.1 Introduction

IPv6

Under IPv6, multicast addresses are those addresses that begin with an 8-bit prefix
of 11111111, or FF, followed by 8 additional bits used to indicate reserved
addresses, well-known addresses, and the scope of the address. The remaining bits
define the multicast group ID. Under IPv6, multicast addresses can be scoped to
the local node, link, site, and so on. IPv6 routers will not forward a multicast packet
beyond the scope of the packet address. For detailed information on IPv6 multicast
addresses, see RFC 3513 and RFC 2375. For information on assigned multicast
addresses, see the IANA online database at:
http://www.iana.org/assignments/ipv6-multicast-addresses
Although IP multicasting is not a link-layer feature, it does require some support
from the underlying network interface driver. You must be able to configure the
network interface to know which multicast groups (addresses) are of interest to it.
When packets addressed to those groups arrive on the interface, the driver passes
the packet up to IP. Otherwise, the driver ignores the packet. All END drivers
currently shipped with the Wind River Network Stack support this ability.
The mechanics by which an application adds its host to a multicast group and
transmits or receives multicast data are usually handled using a UDP socket
connection. An example of how to manage a multicast send and receive is
provided in 13.2.2 Using a Datagram (UDP) Socket to Access IPv4 Multicasting, p.260.

Multicast Routing Protocol

Multicast routing requires a multicast routing protocol implementation and that 18


the network stack includes no such protocol implementation.The required socket
mechanisms for accessing multicast routing functionality are implemented as well
as support for PIM (Protocol Independent Multicasting), although PIM itself is not
implemented. Thus, in order to work with multicast routing on a VxWorks target,
you will need to provide a PIM implementation or some equivalent.
On the routers serving the points in the network to which you want to multicast,
you must run a common multicast routing protocol. On all VxWorks targets
participating in the multicast, both senders and the receivers, you must enable
multicast forwarding in the kernel, and you must run a multicast routing capable
application.

377
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

18.2 Adding IGMP Host and Router Support


Internet Group Management Protocol (IGMP) is used to manage the membership
of multicast groups. IGMP is used by IP hosts and adjacent multicast routers and
is part of the IP multicast specification.

18.2.1 Compiling the Network Stack for IGMP

For the host side of the protocol, whether you get IGMPv2 or IGMPv3 depends on
how the network stack was compiled. The default build creates IGMPv2 modules.
However, if you build the stack with IGMPV3 defined, you create IGMPv3
modules. For the router side of the protocol, the stack supports a V2
implementation but not a V3 implementation.

NOTE: For information on building the network stack, see your Wind River
Platforms Getting Started.

18.2.2 Configuring VxWorks for IGMP

The Wind River Network Stack supports the following host and router
components for IGMP, the protocol that provides multicasting support in the IPv4
domain:

IGMP v4

IGMP Router
These components are listed under the
Network Components > Network Protocol Components >
Network IPv4 Components folder in Workbench.

IGMP v4

The INCLUDE_IGMP component pulls in igmpLib, a library that implements the


host side of IGMPv2 or IGMPv3, depending on whether or not IGMPV3 was
defined when you built the network stack code. The IGMPv2 implementation is
based on RFC 2236. The IGMPv3 host is based on RFC 3376 and the multicasting
socket interface extensions described in section 5 of RFC 3678.
This component requires the INCLUDE_IPV4 configuration component and
contains no configuration parameters.

378
18 Adding IGMP, MLD, and Multicast Routing Support
18.2 Adding IGMP Host and Router Support

NOTE: There are no user-callable routines associated with igmpLib.

Supported Join and Leave Group Options

Both IGMPv2 and IGMPv3 support the socket options MCAST_JOIN_GROUP and
MCAST_LEAVE_GROUP. As described in the RFCs, you can use these socket
options to join or leave multicast groups. To support source filtering, IGMPv3 (but
not IGMPv2) supports four additional options:
MCAST_JOIN_SOURCE_GROUP and MCAST_LEAVE_SOURCE_GROUP
Using the option MCAST_JOIN_SOURCE_GROUP, you identify not only the
group you want to join but also the IPv4 address of the source from which you
will accept multicast packets. To leave the group, you can use either the
standard MCAST_LEAVE_GROUP socket option or the new
MCAST_LEAVE_SOURCE_GROUP socket option. If you use the newer option,
you can be specific about the group and source you are leaving. If you are
registered for more than one source, those other sources remain active. The
MCAST_LEAVE_GROUP socket option removes all sources.
To register for more than one source, some circumstances allow multiple
MCAST_JOIN_SOURCE_GROUP calls. However, the least ambiguous method
is to use the SIOCMSFILTER ioctl, which lets you specify more than one source
in the leave or join command.
For more information on these socket options and the ioctl, see RFC 3678.
MCAST_BLOCK_SOURCE and MCAST_UNBLOCK_SOURCE 18
Using the option MCAST_BLOCK_SOURCE, you identify the group you want
to join as well as the IPv4 address of a source from which you will not accept
multicast packets. To unblock that source, you use
MCAST_UNBLOCK_SOURCE. To block more than one source, some
circumstances allow multiple MCAST_BLOCK_SOURCE calls. However, the
least ambiguous method is to use the SIOCMSFILTER ioctl, which lets you
specify more than one source in the command.
For more information on these socket options and the ioctl, see section 5 of
RFC 3678. The mechanisms described in section 5 are protocol independent.
Alternatively, you could see section 4 of the same RFC. This section describes
a parallel set of options that are IP-specific.

379
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

IGMP Router

The INCLUDE_IGMP_ROUTER component pulls in igmpRouterLib, which


provides a partial implementation of multicast routing using the IGMPv2 protocol.
This component requires the INCLUDE_MROUTE and INCLUDE_IGMP
configuration components and contains no configuration parameters.

NOTE: This component is available only in the Wind River Platforms builds of the
network stack. The Wind River General Purpose Platform, VxWorks Edition, does
not support the IGMP router.

If your custom PIM implementation implements the IGMP router portion of the
protocol, you can exclude INCLUDE_IGMP_ROUTER.

IGMP Router Implementation and Specifications

According to RFC 2236, an IGMPv2 router listens on IGMP-enabled interfaces for


membership reports from networked hosts. Using the membership reports, an
IGMP router constructs and maintains per-interface lists of the multicast addresses
to which IGMP hosts are listening.
To discover when it needs to prune entries from a list, an IGMP router periodically
transmits queries to the multicast groups accessible through a given interface. If no
replies arrive after a specific time, or if a leave message is processed, the IGMP
router removes the group from the list for that interface.
To support its IGMP router implementation, VxWorks relies on an
IGMP-dedicated task that waits on an IGMP-dedicated message queue. This
message queue collects IGMP timer expiration messages as well as IGMP
membership reports.
In response to a timer expiration message, the IGMP router task either removes a
multicast destination from the interface on which it has expired, or the task sends
a query. In response to a membership report, the task processes the packet.
When a new membership report arrives on an interface, the IGMP router only
creates a placeholder entry in the multicast routing table. Integration with other
multicast protocols (such as PIM) is required to create completed entries which
will forward multicast traffic.

IGMPv2 Router API Summary

The IGMPv2 router side API consists of the following routines:



igmpRouterLibInit( ) – initialize the IGMPv2 router

380
18 Adding IGMP, MLD, and Multicast Routing Support
18.2 Adding IGMP Host and Router Support


igmpRouterLibQuit( ) – shut down the IGMPv2 router

igmpInterfaceEnable( ) – enable IGMPv2 on the specified interface

igmpInterfaceDisable( ) – disable IGMPv2 on the specified interface
For detailed information on the above routines, see the igmpRouterLib reference
entries.

IGMPv2 Router Initialization and Termination

If you included INCLUDE_IGMP_ROUTER in your VxWorks image, the VxWorks


start-up code automatically calls igmpRouterLibInit( ). You should have no need
to call igmpRouterLibInit( ) explicitly. If you need to shut down IGMPv2 routing
before shutting down the target, you can call igmpRouterLibQuit( ).

NOTE: An IGMP router necessarily requires that the host device support at least
two network interfaces on which IGMP routing is enabled. Simply including
IGMP is not enough. Neither is enabling it on only one interface.

■ igmpRouterLibInit( ) – initialize the IGMP router


Calling igmpRouterLibInit( ) spawns the IGMP router task and does almost
everything necessary to initialize (but not start) the router side of the IGMPv2
implementation. A call to igmpRouterLibInit( ) returns OK if successful, or
ERROR otherwise, such as when IGMP has already been started. To actually
start IGMP routing, you must enable it on at least two host-local interfaces.

igmpRouterLibQuit( ) – shut down the IGMP router
Calling igmpRouterLibQuit( ) ends IGMP routing by closing the IGMP
18
socket, deleting the router task, and generally cleaning up. An
igmpRouterLibQuit( ) call returns OK if successful, or ERROR otherwise,
such as when IGMP has not been started.

IGMPv2 Router Control

Nothing in VxWorks automatically calls igmpInterfaceEnable( ). You must call


igmpInterfaceEnable( ) explicitly for each network interface on which you want
to enable the IGMPv2 router. Similarly, nothing in VxWorks automatically calls
igmpInterfaceDisable( ). If an IGMPv2 router enabled interface goes down, you
must explicitly call igmpInterfaceDisable( ) for that interface.

igmpInterfaceEnable( ) – enable the IGMP router on the specified interface
Calling igmpInterfaceEnable( ) enables the IGMP router on an interface. You
can call this routine for any interface that is capable of receiving multicast
packets. The IGMPv2 router will not process any messages or timers unless it

381
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

is enabled on at least two interfaces. An igmpInterfaceEnable( ) call returns


OK if successful, or ERROR otherwise, such as when an interface is not
multicast capable.

igmpInterfaceDisable( ) – disable IGMP on the specified interface
Calling igmpInterfaceDisable( ) disables IGMP on an interface. An
igmpInterfaceDisable( ) call returns OK if successful, or ERROR otherwise,
such as when the interface was not enabled.

18.3 Controlling Multicast Routing


To control the multicast routing functionality, you must open a routing socket in
the VxWorks kernel space.

Opening a Multicast Routing Control Socket

Consider the following code:


int mRoutSock;
mRoutSock = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);

Note that if the router needs to open an IGMP control socket (for operations like
adding or deleting MFC entries or virtual interfaces), it should use the same socket
for sending and receiving the IGMP protocol messages.

Enabling Multicast Routing

After you have opened the multicast routing socket, you can use it to enable or
disable multicast forwarding.
Consider the following code:
int version = 1;
setsockopt( mRoutSock, IPPROTO_IP, MRT_INIT, (void *)&version,
sizeof(version) );

After you have enabled multicast forwarding, you can use the multicast routing
socket to enable PIM processing in the kernel. See 18.6 Using PIM, p.392.

382
18 Adding IGMP, MLD, and Multicast Routing Support
18.4 Adding and Deleting Virtual Interfaces for Multicast Routing

18.4 Adding and Deleting Virtual Interfaces for Multicast Routing


For each network interface (physical or a virtual tunnel) that you use for multicast
forwarding, you must add a corresponding multicast interface.

Adding Multicast Routing Virtual Interface

To add a virtual interface for use with multicast routing:


struct vifctl myVc;
memset(&myVc, 0, sizeof(myVc)); /* Assign all fields as needed */
myVc.vifc_vifi = vif_index;
myVc.vifc_flags = vif_flags;
myVc.vifc_threshold = min_ttl_threshold;
myVc.vifc_rate_limit = max_rate_limit;
memcpy(&myVc.vifc_lcl_addr, &vif_local_address,
sizeof(myVc.vifc_lcl_addr));
if (myVc.vifc_flags & VIFF_TUNNEL)
{
memcpy(&myVc.vifc_rmt_addr, &vif_remote_address,
sizeof(myVc.vifc_rmt_addr));
}
setsockopt(mRoutSock, IPPROTO_IP, MRT_ADD_VIF, (void *)&myVc,
sizeof(myVc));

Where:
vif_index
Must be unique for each virtual interface.
vif_flags
Contains the VIFF_flagname flags as defined in <netinet/ip_mroute.h>.
18
min_ttl_threshold
Contains the minimum TTL a multicast data packet must have to be
forwarded on that virtual interface. Typically, it would have a value of 1.
max_rate_limit
Contains the maximum rate (in bits per second) of the multicast data
packets forwarded on that virtual interface. A value of 0 means no limit.
vif_local_address
Contains the local IP address of the corresponding local interface.
vif_remote_address
Contains the remote IP address in case of DVMRP multicast tunnels.

383
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Deleting Virtual Multicast Routing Interfaces

To delete a multicast interface:


vifi_t myViIfIndex = vif_index;
setsockopt(mRoutSock, IPPROTO_IP, MRT_DEL_VIF, (void *)&myViIfIndex,
sizeof(myViIfIndex));

Opening a Multicast Socket for Receiving Upcalls

After multicast forwarding is enabled and the multicast virtual interfaces are
added, the kernel can deliver upcalls on the multicast routing socket that you
opened earlier and for which you have set the options MRT_INIT. The upcalls use
a struct igmpmsg header (see <netinet/ip_mroute.h>) with the im_mbz field set
to zero. Note that this header follows the structure of struct ip with the ip_p
protocol field set to zero.
The upcall header contains im_msgtype field with the type of the upcall
IGMPMSG_type. The values of the rest of the signal header fields and the body of
the signal message depend on the particular signal type.
If the upcall message type is IGMPMSG_NOCACHE, a multicast packet has reached
the multicast router, but the router has no forwarding state for that packet.
Typically, the message is a signal for the multicast routing user-level process to
install the appropriate Multicast Forwarding Cache (MFC) entry in the kernel.
To add an entry to an MFC:
struct mfcctl mc;
memset(&mc, 0, sizeof(mc));
memcpy(&mc.mfcc_origin, &source_addr, sizeof(mc.mfcc_origin));
memcpy(&mc.mfcc_mcastgrp, &group_addr, sizeof(mc.mfcc_mcastgrp));
mc.mfcc_parent = iif_index;
for (i = 0; i < maxvifs; i++)
{
mc.mfcc_ttls[i] = oifs_ttl[i];
}
setsockopt(mRoutSock, IPPROTO_IP, MRT_ADD_MFC, (void *)&mc, sizeof(mc));

source_addr and group_addr


The source and group address of the multicast packet (as set in the upcall
message).
iif_index
The virtual interface index of the multicast interface the multicast packets
for this specific source and group address should be received on.

384
18 Adding IGMP, MLD, and Multicast Routing Support
18.5 Using the Advanced Multicast Routing API

oifs_ttl[ ]
The minimum TTL (per interface) a multicast packet should have to be
forwarded on an outgoing interface. If the TTL value is zero, the
corresponding interface is not included in the set of outgoing interfaces.

Deleting MFS Entries

To delete an MFC entry:


struct mfcctl mc;
memset(&mc, 0, sizeof(mc));
memcpy(&mc.mfcc_origin, &source_addr, sizeof(mc.mfcc_origin));
memcpy(&mc.mfcc_mcastgrp, &group_addr, sizeof(mc.mfcc_mcastgrp));
setsockopt(mRoutSock, IPPROTO_IP, MRT_DEL_MFC, (void *)&mc, sizeof(mc));

Getting Statistics

Use the following method to get statistics for each installed MFC entry, such as the
number of forwarded packets per source and group address:
struct sioc_sg_req sgreq;
memset(&sgreq, 0, sizeof(sgreq));
memcpy(&sgreq.src, &source_addr, sizeof(sgreq.src));
memcpy(&sgreq.grp, &group_addr, sizeof(sgreq.grp));
ioctl(mRoutSock, SIOCGETSGCNT, &sgreq);

The following method can be used to get various statistics per multicast virtual
interface in the kernel, such as the number of forwarded packets for each interface:
struct sioc_vif_req vreq;
memset(&vreq, 0, sizeof(vreq));
vreq.vifi = vif_index;
ioctl(mRoutSock, SIOCGETVIFCNT, &vreq); 18

18.5 Using the Advanced Multicast Routing API


The network stack now supports an enhanced multicasting API. To use the
enhanced API, your application needs to request and negotiate the APIs needed.
This procedure allows your application to be backward compatible so that it can
run on an older release of the stack as well.
1. The application tries to enable in the kernel the set of new features (and the
corresponding API) it would like to use.

385
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

2. The kernel returns the (sub)set of features it knows about and will allow to be
enabled.
3. The application uses only that set of features the kernel has agreed to enable.
To support backward compatibility, if the application does not ask for any new
features, the kernel defaults to the basic multicast API. Below is a summary of the
expandable API solution. Note that all new options and structures are defined in
<netinet/ip_mroute.h>, unless stated otherwise.
The application uses new getsockopt( ) or setsockopt( ) options to negotiate the
API features with the kernel. You must conduct this negotiation right after the
multicast routing socket is open. The set of desired and allowed features is stored
as bits set in a uint32_t (thus, a maximum of 32 new features). The new
getsockopt( ) or setsockopt( ) options are MRT_API_SUPPORT and
MRT_API_CONFIG.
Example:
uint32_t supportedOptions;
getsockopt( mRoutSock, IPPROTO_IP, MRT_API_SUPPORT, (void
*)&supportedOptions,
sizeof(supportedOptions));

In supportedOptions, the getsockopt( ) call would set the pre-defined bits that the
kernel API supports. The 8 least-significant bits in the uint32_t are same as the 8
possible flags, MRT_MFC_FLAGS_flagname, that you can use in mfcc_flags as part of
the new definition of struct mfcctl. This leaves 24 flags for other new features. The
returned value of a call to getsockopt(MRT_API_SUPPORT) is read-only. A
setsockopt(MRT_API_SUPPORT) call would fail.
To modify the API and to set some specific feature in the kernel:
uint32_t v = MRT_MFC_FLAGS_DISABLE_WRONGVIF;
if (setsockopt(mRoutSock, IPPROTO_IP, MRT_API_CONFIG, (void *)&v,
sizeof(v)) != 0)
{
return (ERROR);
}
if (v & MRT_MFC_FLAGS_DISABLE_WRONGVIF)
{
return (OK); /* Success */
}
else
{
return (ERROR);
}

Thus, when you call setsockopt(MRT_API_CONFIG), the argument specifies the


set of features that you want to enable in the API and the kernel. The value

386
18 Adding IGMP, MLD, and Multicast Routing Support
18.5 Using the Advanced Multicast Routing API

returned in v is the actual (sub)set of features that were enabled in the kernel. To
check the enabled features at a later time, call:
getsockopt(mRoutSock, IPPROTO_IP, MRT_API_CONFIG, (void *)&v, sizeof(v));

The set of enabled features is global. In other words, you should call
setsockopt(MRT_API_CONFIG) right after your setsockopt(MRT_INIT) call.
The following set of new features is defined:
/* disable WRONGVIF signals */
#define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0)
#define MRT_MFC_FLAGS_BORDER_VIF(1 << 1) /* border vif */
#define MRT_MFC_RP (1 << 8) /* enable RP address */
#define MRT_MFC_BW_UPCALL(1 << 9) /* enable bw upcalls */

The advanced multicast API uses a newly defined struct mfcctl2 instead of the
traditional struct mfcctl. The original struct mfcctl is kept as is. The new
struct mfcctl2 is as follows:
/*
* The new argument structure for MRT_ADD_MFC and MRT_DEL_MFC overlays
* and extends the old struct mfcctl.
*/

struct mfcctl2 { /* the mfcctl fields */


struct in_addr mfcc_origin;/* ip origin of mcasts */
struct in_addr mfcc_mcastgrp;/* multicast group associated*/
vifi_t mfcc_parent;/* incoming vif */
u_char mfcc_ttls[MAXVIFS];/* forwarding ttls on vifs */

/* extension fields */
uint8_t mfcc_flags[MAXVIFS];/* the MRT_MFC_FLAGS_* flags*/
struct in_addr mfcc_rp; /* the RP address */
}; 18
The new fields are mfcc_flags[MAXVIFS] and mfcc_rp. Note that for
compatibility reasons they are added at the end. Use the
mfcc_flags[MAXVIFS] field to set various flags per interface per entry.
Currently, the defined flags are:
/* disable WRONGVIF signals */
#define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0)
#define MRT_MFC_FLAGS_BORDER_VIF (1 << 1) /* border vif */

Use the MRT_MFC_FLAGS_DISABLE_WRONGVIF flag to explicitly disable the


IGMPMSG_WRONGVIF kernel signal at the (S,G) granularity if a multicast data
packet arrives on the wrong interface.1

1. (S,G) refers to Source, Group. All multicast forward cache entries are based on those two
values. An MFC entry (S,G) states that for a packet coming from Source S and destined to
Group G should be forwarded on these interfaces.

387
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Usually, you use this signal to complete the shortest-path switch in case of PIM-SM
multicast routing, or to trigger a PIM assert message. It should not be delivered for
interfaces that are not in the outgoing interface set and that are not expecting to
become an incoming interface.
Thus, if the MRT_MFC_FLAGS_DISABLE_WRONGVIF flag is set for some of the
interfaces, then a data packet that arrives on that interface for that MFC entry will
not trigger a WRONGVIF signal. If that flag is not set, then a signal is triggered (the
default action).
Use the MRT_MFC_FLAGS_BORDER_VIF flag to specify whether the Border bit in
PIM Register messages should be set (in case when the Register encapsulation is
performed inside the kernel). If it is set for the special PIM Register kernel virtual
interface (see 18.6 Using PIM, p.392), the Border bit in the Register messages sent
to the RP will be set.
The remaining six bits are reserved for future development.
Use the mfcc_rp field to specify the RP address (in case of PIM- SM multicast
routing) for a multicast group G if we want to perform kernel-level PIM Register
encapsulation. Use the mfcc_rp field only if you have called
setsockopt(MRT_API_CONFIG) and successfully set the MRT_MFC_RP advanced
API capability.
If you successfully set the MRT_MFC_RP flag, the kernel tries to do the PIM
Register encapsulation itself instead of sending the packets to the application
(inside IGMPMSG_WHOLEPKT signals) for the application to encapsulate. The RP
address would be taken from the mfcc_rp field inside the new struct mfcctl2. Even
if the MRT_MFC_RP flag was successfully set, if the mfcc_rp field was set to
INADDR_ANY, the kernel still delivers an IGMPMSG_WHOLEPKT signal with the
multicast data packet to an application.
In addition, if the multicast data packet is too large to fit within a single IP packet
after the PIM Register encapsulation (for example, if its size was on the order of
65500 bytes), the data packet will be fragmented and each of the fragments will be
encapsulated separately. Typically, only a locally generated packet can be that
large. Otherwise, the transmission of the multicast data packet over Ethernet
would have already fragmented the packet into much smaller pieces.
In addition, a multicast routing application would need to know the forwarding
bandwidth for some data flow. For example, the multicast routing process may
want to timeout idle MFC entries, or in case of PIM- SM it can initiate (S,G)
shortest-path switch if the bandwidth rate is above a threshold for example.

388
18 Adding IGMP, MLD, and Multicast Routing Support
18.5 Using the Advanced Multicast Routing API

The original solution for measuring the bandwidth of a dataflow was that a
user-level process would periodically query the kernel about the number of
forwarded packets/bytes per (S,G), and then based on those numbers it would
estimate whether a source is idle, or whether the source’s transmission bandwidth
is above a threshold. That solution is far from being scalable, hence the need for a
new mechanism for bandwidth monitoring.
Below is a description of the new bandwidth monitoring mechanism.
■ If the bandwidth of a data flow satisfies some pre-defined filter, the kernel
delivers an upcall on the multicast routing socket to the multicast routing
process that has installed that filter.
■ The bandwidth-upcall filters are installed per (S,G). There can be more than
one filter per (S,G).
■ Instead of supporting all possible comparison operations (that is, <, <=, ==, !=,
>, >= ), there is support only for the <= and >= operations, because this makes
the kernel-level implementation simpler. The missing operations can be
simulated by secondary user-level filtering of the <= and >= filters. For
example, to simulate !=, then we need to install filter ‘‘bw <= 0xffffffff’’, and
after an upcall is received, we need to check whether ‘‘measured_bw !=
expected_bw’’.
■ To enable the bandwidth-signal mechanism for the MRT_MFC_BW_UPCALL
flag, call setsockopt(MRT_API_CONFIG).
■ For bandwidth-signal filters, call setsockopt(MRT_ADD_BW_UPCALL) or
setsockopt(MRT_DEL_BW_UPCALL) to delete or add the filter. Make sure that
you use the appropriate struct bw_upcall argument. 18

From an application point of view, you need to know about the following:
/*
* Structure for installing or delivering an upcall if the
* measured bandwidth is above or below a threshold.
*
* User programs might have a need to know when the bandwidth
* used by some data flow is above or below some threshold.
* This interface allows the userland to specify the threshold
* (in bytes and/or packets) and the measurement interval. Flows
* are all packet with the same source and destination IP address.
* At the moment the code is only used for multicast destinations
* but there is nothing that prevents its use for unicast.
*
* The measurement interval cannot be shorter than some Tmin (currently, 3s)
* The threshold is set in packets and/or bytes per_interval.
*

389
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

* Measurement works as follows:


*
* For >= measurements:
* The first packet marks the start of a measurement interval.
* During an interval we count packets and bytes, and when we
* pass the threshold we deliver an upcall and we are done.
* The first packet after the end(3,7,1 builtin) of the interval
* resets the count and restarts the measurement.
*
* For <= measurement:
* We start a timer to fire at the end(3,7,1 builtin) of the interval,
* and then for each incoming packet we count packets and bytes.
* When the timer fires, we compare the value with the threshold,
* schedule an upcall if we are below, and restart the measurement
* (reschedule timer and zero counters).
*/

struct bw_data
{
struct timeval b_time;
uint64_t b_packets;
uint64_t b_bytes;
};

struct bw_upcall {
struct in_addr bu_src; /* source address */
struct in_addr bu_dst; /* destination address */
uint32_t bu_flags; /* misc flags (see below) */
#define BW_UPCALL_UNIT_PACKETS (1 << 0) /* threshold (in packets) */
#define BW_UPCALL_UNIT_BYTES (1 << 1) /* threshold (in bytes) */
#define BW_UPCALL_GEQ (1 << 2) /* upcall if bw >= threshold */
#define BW_UPCALL_LEQ (1 << 3) /* upcall if bw <= threshold */
#define BW_UPCALL_DELETE_ALL (1 << 4) /* delete(7,n) all upcalls for s,d */
struct bw_data bu_threshold; /* the bw threshold */
struct bw_data bu_measured; /* the measured bw */
};
/* max. number of upcalls to deliver together */
#define BW_UPCALLS_MAX 128
/* min. threshold time interval for bandwidth measurement */
#define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC 3
#define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC 0

The bw_upcall structure is used as an argument to


setsockopt(MRT_ADD_BW_UPCALL) and setsockopt(MRT_DEL_BW_UPCALL).
Each setsockopt(MRT_ADD_BW_UPCALL) call installs a filter in the kernel for the
source and destination address in the bw_upcall argument, and that filter triggers
an upcall according to the following pseudo-algorithm:
if (bw_upcall_oper IS ">=") {
if (((bw_upcall_unit & PACKETS == PACKETS) &&
(measured_packets >= threshold_packets)) ||
((bw_upcall_unit & BYTES == BYTES) &&
(measured_bytes >= threshold_bytes)))
SEND_UPCALL("measured bandwidth is >= threshold"); }

390
18 Adding IGMP, MLD, and Multicast Routing Support
18.5 Using the Advanced Multicast Routing API

if (bw_upcall_oper IS "<=" && measured_interval >= threshold_interval) {


if (((bw_upcall_unit & PACKETS == PACKETS) &&
(measured_packets <= threshold_packets)) ||
((bw_upcall_unit & BYTES == BYTES) &&
(measured_bytes <= threshold_bytes)))
SEND_UPCALL("measured bandwidth is <= threshold");
}

In the same bw_upcall the unit can be specified in both BYTES and PACKETS. The
GEQ and LEQ flags are mutually exclusive.
An upcall is delivered if the measured bandwidth is >= or <= the threshold
bandwidth (within the specified measurement interval). For practical reasons, the
smallest value for the measurement interval is 3 seconds. If smaller values were
allowed, then the bandwidth estimation may be less accurate, or the potentially
very high frequency of the generated upcalls may introduce too much overhead.
For the >= operation, the answer may be known before the end of
threshold_interval, therefore the upcall may be delivered earlier.
For the <= operation, one must wait until the threshold interval has expired to
know the answer.
Example usage:
struct bw_upcall bw_upcall;
/* Assign all bw_upcall fields as appropriate */
memset(&bw_upcall, 0, sizeof(bw_upcall));
memcpy(&bw_upcall.bu_src, &source, sizeof(bw_upcall.bu_src));
memcpy(&bw_upcall.bu_dst, &group, sizeof(bw_upcall.bu_dst));
bw_upcall.bu_threshold.b_data = threshold_interval;
bw_upcall.bu_threshold.b_packets = threshold_packets;
bw_upcall.bu_threshold.b_bytes = threshold_bytes;
if (is_threshold_in_packets) 18
{
bw_upcall.bu_flags |= BW_UPCALL_UNIT_PACKETS;
}
if (is_threshold_in_bytes)
{
bw_upcall.bu_flags |= BW_UPCALL_UNIT_BYTES;
}

do {
if (is_geq_upcall)
{
bw_upcall.bu_flags |= BW_UPCALL_GEQ;
break;
}
if (is_leq_upcall)
{
bw_upcall.bu_flags |= BW_UPCALL_LEQ;
break;
}
return (ERROR);

391
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

} while (0);
setsockopt(mRoutSock, IPPROTO_IP, MRT_ADD_BW_UPCALL,
(void *)&bw_upcall, sizeof(bw_upcall));

To delete a single filter, use MRT_DEL_BW_UPCALL. The fields of bw_upcall must


be set exactly same as when MRT_ADD_BW_UPCALL was called.
To delete all bandwidth filters for a given (S,G), only the bu_src and bu_dst fields
in struct bw_upcall need to be set, and then just set only the
BW_UPCALL_DELETE_ALL flag inside the bw_upcall.bu_flags field.
The bandwidth upcalls are received by aggregating them in the new upcall
message:
#define IGMPMSG_BW_UPCALL 4 /* BW monitoring upcall */

This message is an array of struct bw_upcall elements (up to BW_UPCALLS_MAX


= 128). The upcalls are delivered when there are 128 pending upcalls, or when 1
second has expired since the previous upcall (whichever comes first). In a
struct upcall element, the bu_measured field is filled in to indicate the particular
measured values. Because of the way the particular intervals are measured, you
should be careful how you use bu_measured.b_time. For example, if the filter is
installed to trigger an upcall if the number of packets is >= 1, then bu_measured
could have a value of zero in the upcalls after the first one. This is because the
measured interval for >= filters is clocked by the forwarded packets. Thus, you
should not use this upcall mechanism for measuring the exact value of the
bandwidth of the forwarded data. To measure the exact bandwidth, get the
forwarded packets statistics using a call to ioctl(SIOCGETSGCNT).
Note that the upcalls for a filter are delivered until the specific filter is deleted, but
no more frequently than once per bu_threshold.b_time. For example, if the filter
is specified to deliver a signal if bw >= 1 packet, the first packet triggers a signal,
but the next upcall is triggered no earlier than bu_threshold.b_time after the
previous upcall.

18.6 Using PIM


The Wind River Network Stack does not include a PIM implementation. If you
write or port a PIM implementation, you can access it in the standard way
described below.

392
18 Adding IGMP, MLD, and Multicast Routing Support
18.6 Using PIM

What is PIM?

PIM is the common name for two multicast routing protocols: Protocol
Independent Multicast - Sparse Mode (PIM-SM) and Protocol Independent
Multicast - Dense Mode (PIM-DM).
PIM-SM
PIM-SM is a multicast routing protocol that can use the underlying unicast
routing information base or a separate multicast-capable routing information
base. It builds unidirectional shared trees rooted at a Rendezvous Point (RP)
per group, and optionally creates shortest-path trees per source.
PIM-DM
PIM-DM is a multicast routing protocol that uses the underlying unicast
routing information base to flood multicast datagrams to all multicast routers.
Prune messages are used to prevent future datagrams from propagating to
routers with no group membership information.
Both PIM-SM and PIM-DM are fairly complex protocols, although PIM-SM is
much more complex than PIM-DM. To enable PIM-SM or PIM-DM multicast
routing in a router, you must enable multicast routing and PIM processing in the
kernel, and run a PIM-SM or PIM-DM capable application.

Using a Socket Interface to Enable and Access PIM Functionality

After opening a multicast routing socket and enabling multicast forwarding, use
one of the following socket options to enable or disable PIM processing in the
18
kernel:
int version = 1;
setsockopt( mRoutSock, IPPROTO_IP, MRT_INIT, (void *)&version,
sizeof(version) );

After you have enabled PIM processing, add the multicast-capable interfaces (see
Adding Multicast Routing Virtual Interface, p.383). In case of PIM-SM, you must also
add the PIM-Register virtual interface. To do this, use the following options:
struct vifctl vc;
memset(&vc, 0, sizeof(vc)); /* Assign all vifctl fields as needed. */
...
if (is_pim_register_vif)
{
vc.vifc_flags |= VIFF_REGISTER;
}
setsockopt(mRoutSock, IPPROTO_IP, MRT_ADD_VIF, (void *)&vc, sizeof(vc));

393
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

To send or receive PIM packets, first you must open a “raw socket” (see the
socket( ) reference entry), with protocol value of IPPROTO_PIM:
int pim_s4;
pim_s4 = socket(AF_INET, SOCK_RAW, IPPROTO_PIM);

After opening the raw socket for PIM, send or receive PIM packets on that socket
by calling sendto( ), sendmsg( ), recvfrom( ), or recvmsg( ).

18.7 Configuring and Using MLD Hosts and Routers


Multicast Listener Discovery (MLD) is one of the protocols needed to support
multicasting in the IPv6 domain. A router can use this protocol to discover the
presence of multicast listeners on directly attached links. Routers can also use it to
discover which multicast addresses are of interest to those neighboring nodes.

NOTE: The e MLD and MLDv2 protocols are available only in the Wind River
Platforms builds of the network stack. The Wind River General Purpose Platform,
VxWorks Edition, does not support these features

18.7.1 Compiling the Network Stack for MLD

The network stack includes an implementation of the host and router sides of the
protocol for both MLDv1 and MLDv2. Because the network stack does not include
a PIM implementation, the MLDv2 router implementation cannot act as a true
MLDv2 router, but it can act as a relay agent that proxies for a PIM-coupled
MLDv2 router.
For the host side of the protocol, whether you get MLDv1 or MLDv2 depends on
how the network stack was compiled. The default build creates MLDv1 modules.
However, if you build the stack with MLDV2 defined, you create MLDv2 modules
that can be configured to operate in MLDv1-only mode, MLDv2-only mode, or
MLDv2 with MLDv1 compatible mode. For the router side of the protocol, the
stack supports a MLDv2 implementation that can be configured on a per-interface
basis to operate in MLDv1-only mode, MLDv2-only mode, or MLDv2 with
MLDv1 compatible mode. To create the MLDv2 modules, you must compile the
stack with MLDV2 defined.

394
18 Adding IGMP, MLD, and Multicast Routing Support
18.7 Configuring and Using MLD Hosts and Routers

NOTE: For information on building the network stack, see your Wind River
Platforms Getting Started.

18.7.2 Configuring VxWorks for MLD

The Wind River Network Stack supports the following MLD host and router
components:
■ MLD

IPv6 MLDv2 Proxy Router
These components are listed under the
Network Components > Network Protocol Components >
Network IPv6 Components folder in Workbench.

MLD

The INCLUDE_MLD component adds MLD host support to a VxWorks image


(MLD is a required component for IPv6 support). This component requires the
INCLUDE_IPV6 component.

INCLUDE_MLD pulls in the mld6 and mldLib libraries, which implement the host
side of MLD. Whether it is an MLDv1 or MLDv2 implementation depends on
whether MLDV2 was defined when you built the network stack code. The MLDv1
implementation implements RFC 2710. The MLDv2 host implements RFC 3810,
18
and the multicasting socket interface extensions described in section 5 of RFC 3678.

NOTE: There are no user-callable routines associated with mldLib.

This component contains the following configuration parameters, which are


MLDv2-specific.

ICMPV6CTL_MLD_MAXSRCFILTER_CFG

Synopsis: MLD max number of MSF per group.


Default: 128

ICMPV6CTL_MLD_SOMAXSRC_CFG

Synopsis: MLD max number of MSF per socket.


Default: 64

395
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

ICMPV6CTL_MLD_VERSION_CFG

Synopsis: MLD version; 0:mldv2 with compat mode; 1:mldv1-only; 2:mldv2


only.
Default: 0
As described in the RFCs, you can use socket options to join or leave multicast
groups. In addition to the MLDv1 socket options, MLDv2 adds the following
socket options:

MCAST_JOIN_GROUP

MCAST_BLOCK_SOURCE

MCAST_UNBLOCK_SOURCE

MCAST_LEAVE_GROUP

MCAST_JOIN_SOURCE_GROUP

MCAST_LEAVE_SOURCE_GROUP

MCAST_LEAVE_GROUP

MLDv2 also adds support for two new ioctls, SIOCGMSFILTER and
SIOCSMSFILTER. For more information on these socket options and the ioctls, see
section 5 and 8.2 of RFC 3678.

IPv6 MLDv2 Proxy Router

The INCLUDE_MLD6_ROUTER component lets you set up a VxWorks target to act


as a relay router for multicast packets. Currently, the Wind River Network Stack
does not include a PIM implementation. Thus, a VxWorks target cannot itself
directly propagate group add and group leave messages. However, it can forward
those messages to a PIM-coupled MLD router that handles add and leave
messages.

NOTE: Wind River MLD Router implementation is an IPv6-only feature, and it


assumes that IPv6 routing is enabled. For details, see 18.7.4 Run-time Configuration
Considerations, p.397.

To act as a relay agent, the target requires at least two interfaces. One interface (and
only one interface) is configured as an MLD proxy. This interface sits on a network
through which it can access a PIM-coupled MLD router. All other interfaces listed
in the configuration file without the proxy flag connect to subnets for which this
target acts as a proxy MLD router.

396
18 Adding IGMP, MLD, and Multicast Routing Support
18.7 Configuring and Using MLD Hosts and Routers

The following are known issues associated with the MLD router implementation:

MLD router does not work on an interface that is dynamically added after the
MLD router daemon has been started. To enable multicasting on such an
interface, you must edit the MLD configuration file, use mldrShutdown to
shutdown the MLD daemon, and then restart the MLD daemon using mldr.

SNMP for MLDv2 MIB is not supported.
■ If you are running more than one stack instance on a target (virtual stacks) be
aware that the MLDv2 proxy router is supported on a single stack instance
only.
■ When reading the source code, be aware that although the source code
contains comments with references to the PIM protocol, the PIM protocol is
not implemented.

18.7.3 Build-Time Configuration Considerations

The default setting for NUM_SYS_64 is not sufficient for multicast routing. Change
the NUM_SYS_64 allocation to a value of at least 500, and then rebuild your
VxWorks image. For details, see 3. Configuring and Managing Memory.
If you want to use netstat( ) to display information on the multicast interface
tables, multicast routing tables, and the multicast forwarding cache, include the
INCLUDE_NETSTAT_MROUTEV6 component in your image.

18
18.7.4 Run-time Configuration Considerations

Before attempting to enable the MLD router on a target, make sure that IPv6
routing is enabled. To do this, you can call Sysctl as follows:
-> Sysctl "net.inet6.ip6.forwarding=1"

You can now call mldr from the command line to start up the MLD router. For a
full listing of the options for this command, see the mldr reference entry. Among
the command-line options, the most fundamental is -c, which lets you specify the
configuration file that the MLD router daemon reads at startup. Using this file, you
can perform the following tasks:

Enable or disable multicasting on a given interface.

Set the MLD mode for each interface.

397
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


Set protocol-specific configuration parameters such as MLD version. Default
values apply if you do not specify a custom value.
Consider the following sample contents of an MLD proxy router configuration file,
for a target with four interfaces, dc0, fei0, fei1, and fei2:
phyint dc0 disable;
phyint fei0 mld_version any;
phyint fei1 mld_version any;
phyint fei2 mld_version any proxy_enable;

MLD is disabled on dc0 and enabled on the remaining three. The fei0 and fei1
interfaces listen to MLD hosts on their respective subnets. The fei2 interface
proxies MLD requests to a PIM-coupled MLD router accessible from its subnet.
Assuming this information is contained in the file, mldr.conf, you could use mldr
from the command line to startup the MLD router. For example:
-> mldr "-c mldr.conf"

For more information on the options available through mldr and its configuration
file, see the reference entry for mldr.

398
19
ALTQ

19.1 Introduction 399


19.2 Supported Queueing Disciplines and Features 400
19.3 Compatibility with VxWorks Features 405
19.4 Building the Network Stack to Include ALTQ 406
19.5 The altqConfig Utility 410
19.6 Rules and Rule Groups for Assigning Packets to Queues 419
19.7 Examples 420
19.8 Sample Code for Pentium Processor Machine-Clock Routines 428

19.1 Introduction
A queueing discipline controls outgoing packets through either a scheduling
mechanism or the management of queue buffers. ALTQ (ALTernate Queueing)
provides queuing disciplines and other features that are useful for supporting
network Quality of Service (QoS). ALTQ was originally developed by the KAME
project (www.kame.net) and has been incorporated in several Unix-based
operating systems. The Wind River implementation of ALTQ is a port of the ALTQ
implementation in FreeBSD 6.0 (see http://www.freebsd.org). For information

399
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

about the queueing disciplines supported in the current release of Wind River’s
ALTQ, see 19.2 Supported Queueing Disciplines and Features, p.400.
To make use of a queueing discipline, there needs to be a way to assign packets to
queues. For Wind River ALTQ, this is done through rules and rule groups
provided by the Wind River Firewall product. Wind River Firewall uses
user-defined rules and rule groups to inspect packets and decide on which to
accept and which to reject. The current release of Firewall contains extensions that
also allow the assignment of packets to ALTQ queues. For information about rules
and rule groups in Wind River Firewall, see Wind River Firewall and NAT
Programmer’s Guide. For information on defining rules and rule groups for ALTQ,
see 19.6 Rules and Rule Groups for Assigning Packets to Queues, p.419 and
19.7 Examples, p.420.
A consequence of using Wind River Firewall with ALTQ is that when you build
VxWorks to include ALTQ, you must also include the Firewall IP Filter
(INCLUDE_FIREWALL_IP_FILTER) build component in your build (see
19.4 Building the Network Stack to Include ALTQ, p.406).
Central to using Wind River ALTQ is the the altqConfg command-line utility. You
use ALTQ to define all ALTQ queues, assign priorities and bandwidths to queues,
and assign queues to network interfaces. You can also use the altqConfg utility to
display information about queues and interfaces. For information on using
altqConfg, see 19.5 The altqConfig Utility, p.410.

NOTE: ALTQ is available only in Wind River Platforms builds of the network stack.
The Wind River General Purpose Platform, VxWorks Edition, does not support
ALTQ.

19.2 Supported Queueing Disciplines and Features


In ALTQ, queues and a queueing discipline are assigned to individual network
interfaces. Only one packet-scheduling discipline can be assigned to an interface.
Wind River ALTQ supports the following packet-scheduling disciplines:

Priority queueing (see 19.2.1 Priority Queueing (PriorityQ), p.401)

Class-based queueing (see 19.2.2 Class-based queueing (CBQ), p.401)

400
19 ALTQ
19.2 Supported Queueing Disciplines and Features

The current release of Wind River ALTQ does not support Hierarchical Fair Service
Curve (HFSC) packet scheduling, which is a part of FreeBSD’s ALTQ
implementation.
Wind River ALTQ supports the following queue buffer-management discipline:

Random Early Detection (RED; see 19.2.3 Random Early Detection (RED), p.403)
In addition, Wind River ALTQ supports Explicit Congestion Notification (ECN;
see 19.2.4 Explicit Congestion Notification (ECN), p.404) and control of
outgoing-packet flow through a token-bucket regulator mechanism (19.2.5 Token
Bucket Regulator, p.404).

19.2.1 Priority Queueing (PriorityQ)

In priority queueing, packets are assigned to queues and sent according to the
priority of their queue. The implementation provides 16 priority levels, 0-15,
with the higher number specifying a higher priority.

19.2.2 Class-based queueing (CBQ)

In class-based queueing, an interface is assigned queues that can be structured


hierarchically, with one queue the child, or subqueue, of another. The user assigns
queues a bandwidth and a priority that determine the order in which packets are
sent. The implementation provides 8 priority levels, 0-7, with the higher number
specifying a higher priority.

Figure 19-1 CBQ interface with root queue and user-defined queues 19

CBQ Interface

Root queue

Queue1 Queue2 Queue3


User-defined
queues
Queue4 Queue5

401
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

All user-defined queues are descendents of an implicit root queue that


corresponds to the interface itself. Figure 19-1 illustrates a possible hierarchy of
queues.

CBQ Bandwidth

The user allocates a CBQ interface an over all bandwidth, which is either a
percentage of available bandwidth at the interface or a specific bit rate (for
example, 2 Mb/second), and assigns each user-defined queue both a bandwidth
and a priority. The root queue is always assigned the bandwidth of its interface. In
assigning bandwidth to user-defined queues, the bandwidth allocated to a parent
queue is distributed across its children. Figure 19-2 shows a possible allocation of
bandwidth for the hierarchy illustrated in Figure 19-1.

Figure 19-2 CBQ interface with queues, subqueues, and bandwidth assignments

CBQ Interface
(10 Mb/sec)

Queue1 Queue2 Queue3


(5 Mb/sec) (2 Mb/sec) (3 Mb/sec)

Queue4 Queue5
(3 Mb/sec) (2 Mb/sec)

Typically, the bandwidth allocated to a parent queue is fully distributed to its


children, but this is not a requirement.

402
19 ALTQ
19.2 Supported Queueing Disciplines and Features

CBQ Priority

Individual queues are assigned a priority. There are seven priority levels. Priority
level is used to determine the order in which packets are sent according to the
following rules:

No packets are sent from queues that have exceeded the average send rate
allowed by their bandwidth (unless borrowing is allowed, see Borrowing
Bandwidth, p.403).
■ Among queues that are within their bandwidth allocation, queues with the
highest level of priority always send queued packets before lower priority
queues.
■ Packets are sent round robin from queues at the same priority level
■ Packets in queues at a lower priority level are sent only when there are no
waiting packets at higher priority queues, as long as those queues are within
their bandwidth limit.

Borrowing Bandwidth

You can specify that an individual child queue is able to borrow bandwidth from
its parent. In this case, when the child queue is on the point of exceeding its
allocated bandwidth, it can make use of any unused bandwidth allocated to its
parent.

19.2.3 Random Early Detection (RED)

You have the option of specifying that individual queues use RED. 19

RED is a buffer-management discipline used with both priority and class-based


queues. Its goal is to prevent queues from becoming too full. It does this as follows:

RED monitors the average size of a queue in respect to maximum and
minimum queue lengths that it derives from the user-configured maximum
length of a queue.
RED calculates the maximum and minimum queue lengths it uses as follows:
– maximum queue length is 30% of the user-configured maximum length
– minimum queue length is 10% of the user-configured maximum

As long as the average size of a queue is below the minimum length, RED takes
no action.

403
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0


When the average length of a queue falls between the maximum and the
minimum, the action RED takes depends on whether explicit congestion
notification (ECN; see 19.2.4 Explicit Congestion Notification (ECN), p.404) is in
effect.
Without ECN, RED drops packets that it selects according to a probabilistic
algorithm based on the average size of the queue.
With ECN, instead of dropping packets, RED marks them by setting a bit in the
packet header. Packets are selected according to the same algorithm used for
dropping packets.
■ When the average length of a queue is above the maximum length, all packets
arriving at the queue are dropped.
■ If an interface has multiple connections with queues whose average size is
above the minimum, RED randomly chooses which connection to act on.

19.2.4 Explicit Congestion Notification (ECN)

You have the option of specifying that a queue uses ECN.


ECN works in conjunction with RED. Instead of dropping packets when average
queue length is between the minimum and maximum queue lengths, ECN sets a
bit in the packet headers of selected packets (see the preceding section). This makes
it possible for the recipient of such packets to recognize that the network is
congested and make allowance for it.
More importantly, ECN sends a congestion notification to the sender of such
packets. Without ECN, packets are dropped and never reach their destination. The
sender only learns about non-delivery and possible network congestion when its
wait period for getting a response from the recipient expires. ECN makes it
possible for the sender to take early action and, for example, slow the rate at which
it sends packets.

19.2.5 Token Bucket Regulator

A token bucket regulator is a way of regulating the flow of outgoing packets in


order to prevent network congestion. It ensures an average rate of byte
transmission on a queue or interface without preventing periods of burstiness. The
basic metaphor is of a bucket filling up with liquid ( corresponding to bytes). You
cannot pour out more liquid (send more bytes) than are contained in the bucket at
a given time.

404
19 ALTQ
19.3 Compatibility with VxWorks Features

A token bucket regulator works as follows:


1. The token bucket fills with bytes at a constant rate. In Wind River ALTQ, this
rate is based on the bandwidth allocated to an interface.
The fill rate determines the average rate at which bytes can be sent.
2. The bucket has a limited depth, or size, in bytes.
You can set the size through the altqConfig altqif tbrsize subcommand (see
tbrsize in Table 19-5 in section 19.5 The altqConfig Utility, p.410). If you do not
explicitly set a value, VxWorks calculates a default tbrsize based on the
bandwidth allocated to the interface and the maximum transmission unit
(MTU) of the interface.
3. Packets are sent based on the number of bytes in the token bucket:
■ If there are as many or more bytes in the bucket than a packet requires, the
packet is sent.
■ In the current release, if there are fewer bytes in the bucket than a packet
requires, the packet is dropped.
■ As long as there are enough bytes in the bucket, a burst of packets can be
sent.
4. When a packet is sent, the number of bytes in the bucket is decremented by the
number of bytes in the packet.
A token bucket regulator applies to individual ALTQ interfaces and is always in
effect.

19

19.3 Compatibility with VxWorks Features


If you include ALTQ in a VxWorks build, you should be aware of the following
restrictions:

ALTQ is not compatible with the VxWorks virtual stacks feature.

The API to the altqConfig utility is not available to applications running in a
real-time process (RTP).

405
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

19.4 Building the Network Stack to Include ALTQ


Including ALTQ in the network stack requires that you also include Wind River
Firewall in your build. At a minimum, this requires that you include the following
Firewall build component in your build:

Firewall IP Filter (INCLUDE_FIREWALL_IP_FILTER)
For information on building VxWorks to include Firewall, see Wind River Firewall
and NAT for VxWorks 6 User’s Guide: Chapter 2, Including Wind River Firewall in
VxWorks.
You can build VxWorks from Workbench or from the command line. Figure 19-3
shows the ALTQ build components and parameters as they appear in the
Workbench component tree:

Figure 19-3 ALTQ Build Components in the Workbench Configuration Tree

406
19 ALTQ
19.4 Building the Network Stack to Include ALTQ

Table 19-1 lists and describes the ALTQ build components. The first column gives
the names of build components as they appear in Workbench. The second column
gives the corresponding INCLUDE macros you need to enter in the config.h file
for a specific BSP when you perform a BSP command-line build.

Table 19-1 ALTQ build components

Workbench config.h Description

ALTQ configuration INCLUDE_ Enables use of the altConfig command-line utility


utility ALTQ_CONFIG (see 19.5 The altqConfig Utility, p.410).

Class-Based INCLUDE_ Required for class-based queueing. When this


Queueing ALTQ_CBQ component is included, the Random Early Detection
(INCLUDE_ALTQ_RED) and RED with In and Out
(INCLUDE_ALTQ_RIO) components are also
included.

Priority Queueing INCLUDE_ Required for priority queueing. When this


ALTQ_PRIORITYQ component is included, the Random Early Detection
(INCLUDE_ALTQ_RED) and RED with In and Out
(INCLUDE_ALTQ_RIO) components are also
included.

Random Early INCLUDE_ This component is automatically included when you


Detection ALTQ_RED include either class-based queueing or priority
queueing.

RED with In and Out INCLUDE_ RIO is not supported in the current release. This
ALTQ_RIO component is automatically included when you
19
include either class-based queueing or priority
queueing, but has no effect.

WRS ALTQ INCLUDE_ALTQ The core ALTQ component, always required. This
component contains a number of parameters, some of
which apply to general queue settings for ALTQ (for
example, maximum number of ALTQ queues), and
others of which apply to the machine-clock used with
a processor. For information on the parameters, see
19.4.1 ALTQ Static Configuration Parameters, p.408.

407
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

19.4.1 ALTQ Static Configuration Parameters

The Alternate Queueing Framework build component contains the parameters


listed in Table 19-2.

Table 19-2 Alternate Queueing Framework parameters

Default
Workbench config.h Value Description

Default Queue ALTQ_DEFAULT_ 50 The default maximum length of an


Limit QUEUE_LIMIT individual queue. This value is used if a
queue is not assigned a maximum length
through the altqConfig utility.

Default Queue ALTQ_DEFAULT_ 1 The default priority assigned to a queue.


Priority QUEUE_PRIORITY This value is used if a queue is not
assigned a priority through the
altqConfig utility.

Dispatch Queue ALTQ_DISPATCH_ 1 The maximum length of the dispatch


Max Length QUEUE_MAX_LEN queue allocated for the network driver.
When a packet is released from an ALTQ
queue, if the network driver is too busy to
send it, it is held in a dispatch queue until
the driver is ready.
The default value of 1 is generally
recommended. Increasing the value may
increase send latencies, although it can
also reduce the number of packets
dropped by the ALTQ queue.

Machine-clock ALTQ_MACH_ 0 The frequency of the machine clock.


frequency CLOCK_FREQ VxWorks uses the frequency in
calculating the token bucket rate for
interfaces (see 19.2.5 Token Bucket
Regulator, p.404).
If the default value of 0 is not changed,
VxWorks emulates a clock frequency of
256 MHz.

408
19 ALTQ
19.4 Building the Network Stack to Include ALTQ

Table 19-2 Alternate Queueing Framework parameters (cont’d)

Default
Workbench config.h Value Description

Machine-clock init ALTQ_ NULL Either NULL or the name of a


routine MACH_CLOCK_ user-implemented routine for initializing
INIT_HOOK the machine clock. If NULL, VxWorks
provides software emulation of
initializing a high-resolution machine
clock.
If you want to use your own hardware
initialization routine, enter the name of
the routine and make sure that the file
defining your routine is included in your
VxWorks project. For sample code to use
in writing an initialization routine for
Pentium processors, see 19.8 Sample Code
for Pentium Processor Machine-Clock
Routines, p.428.

Machine-clock read ALTQ_ NULL Either NULL or the name of a


routine MACH_CLOCK_ user-implemented routine for reading the
READ_HOOK machine clock. If NULL, VxWorks
provides software emulation of reading a
high-resolution machine clock.
If you want to use your own hardware
read routine, enter the name of the routine
and make sure that the file defining the 19
routine is included in your VxWorks
project. For sample code to use in writing
a read routine for Pentium processors, see
19.8 Sample Code for Pentium Processor
Machine-Clock Routines, p.428.

409
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

Table 19-2 Alternate Queueing Framework parameters (cont’d)

Default
Workbench config.h Value Description

Maximum Number ALTQ_MAX_QUEUE_ 100 The maximum number of ALTQ queues


ALTQ Queues ALLOWED allowed on the system.

Use machine clock ALTQ_USE_MACH_ FALSE Whether to use the machine clock. If
CLOCK FALSE, software emulation of a machine
clock is used.
If you set the value to TRUE, you need to
provide machine-clock initialization and
read routines (see the table entries for
Machine-clock init routine and
Machine-clock read routine).

19.5 The altqConfig Utility


The altqConfig utility is used to configure all queues and to assign queues to
interfaces. This section lists the basic ALTQ commands (see Basic altqConfig
Commands, p.411), provides guidelines for the order in which queues are
configured and assigned to interfaces (see 19.5.2 Guidelines for Using altqConfig,
p.412), and gives information about each of the subcommands available through
altqConfig (see 19.5.3 The altqConfig queue Command and Subcommands, p.413 and
19.5.4 The altqConfig altqif Command and Subcommands, p.416)

410
19 ALTQ
19.5 The altqConfig Utility

19.5.1 Basic altqConfig Commands

Table 19-3 lists the basic altqConfig commands. Note that the entire command
following altqConfig is enclosed in quotes.

Table 19-3 Basic altqConfig Commands

Command Description

altqConfig The two commands are equivalent. Both list


altqConfig "show "
configuration information about the currently defined
ALTQ queues and the interfaces to which they are
assigned. For an example, see altqConfig "show", p.426.
altqConfig [ "altq on " | "altq off "] The altqConfig "altq on" command turns on ALTQ for
all interfaces that have ALTQ queues. The altqConfig
"altq off" command turns off ALTQ for all interfaces
that have ALTQ queues.
To turn ALTQ on for an individual interface, use the
command altqConfig "altqif interface_name enable"; to
turn ALTQ off for an individual interface, use the
command altqConfig "altqif interface_name disable".
altqConfig "queue queue_name subcommands" Allows you to add, remove or configure a queue. There
may be one or more subcommands, and a subcommand
may take one or more arguments. For the altqConfig
queue subcommands, see 19.5.3 The altqConfig queue
Command and Subcommands, p.413.
altqConfig "altqif if_name subcommands " Allows you to add queues to an interface, remove 19
queues from an interface, and to configure
characteristics of an interface for ALTQ. For the
altqConfig altqif subcommands, see 19.5.4 The
altqConfig altqif Command and Subcommands, p.416.
altqConfig "-h " ■
altqConfig "-h" displays help for all altqConfig
altqConfig "-h queue "
altqConfig "-h altqif "
commands

altqConfig "-h queue" displays help for all
altqConfig queue commands

altqConfig "-h altqif" displays help for all
altqConfig altqif commands

411
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

19.5.2 Guidelines for Using altqConfig

You use altqConfig queue subcommands (see 19.5.3 The altqConfig queue Command
and Subcommands, p.413) to define and configure queues. The altqConfig "queue
queue_name enable" command makes a queue, once configured, available for use.
You use altqConfig altqif (see 19.5.4 The altqConfig altqif Command and
Subcommands, p.416) subcommands to configure interfaces and assign queues to
them. The altqConfig "altqif if_name enable" command makes an interface
available for use.
As long as no queues or interfaces have been enabled, you can make any
configuration changes you want. However, there are a number of constraints on
when you can enable queues and interfaces and what changes you can make after
enabling queues and interfaces:
■ Before an interface can be enabled, all the queues assigned to it must be
enabled.
■ If a queue has children (class-based queueing), all of its children must be
enabled before it can be enabled.
■ You can make changes to a queue, as long as it is not associated with an
enabled interface.
To make changes to a queue that has already been enabled, you must first
disable the queue (altqConfig "queue queue_name disable"
■ Once an interface has been enabled, you cannot make any changes in the way
it is configured.
The only way to make changes to the configuration of an interface is to remove
the interface from ALTQ (altqConfig "altqif interface_name remove") and then
add it back to ALTQ (altqConfig "altqif interface_name add") and completely
reconfigure it.
■ Before you can turn ALTQ on (altqConfig "altq on") at least one interface must
be enabled.

Once you have turned altqConfig on, if you want to enable additional
interfaces, you need to turn altqConfig off, make the changes, and then turn
altqConfig on, again.
The following is a simple sequence of altqConfig steps for initial setup:
1. Use altqConfig queue commands to define one or more queues and their
properties.
2. Use altqConfig altqif commands to configure and assign queues to interfaces.

412
19 ALTQ
19.5 The altqConfig Utility

3. Enable the queues you set up, then enable the interfaces they are associated
with.
4. To confirm you have configured queues and interfaces as wished, use either
altqConfig with no argument or altqConfig show to display the properties of
all ALTQ queues and interfaces.
For sample output see altqConfig "show", p.426.
5. If the output from the previous step is satisfactory, turn ALTQ on.

19.5.3 The altqConfig queue Command and Subcommands

Use the altqConfig queue command with the name of a queue to configure a
queue for ALTQ or to display information about an individual queue. The form of
the command is:
altqConfig "queue if_name subcommand1[, subcommand2[, subcommand3[, ...]]"
Note that the portion of the command following altqConfig must be enclosed in
quotes.
Subcommands can be given in any order, following if_name. The following
altqConfig queue command creates the class-based queue Queue1 as the default
queue for its interface and assigns two subqueues to it, subQ1 and subQ2:
altqConfig "queue Queue1 scheduler cbq default qlist subQ1
subQ2"
In addition to the altqConfig queue commands that specify a queue name, there
are two altqConfig queue commands that do not take a queue name and display
19
configuration information about all queues:
altqConfig "queue"
altqConfig "queue show"
These commands are equivalent to each other and display the same configuration
information for queues that the altqConfig and altqConfig show commands do
(see 19.7.3 Sample Output from altqConfig, p.426).

413
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

Table 19-4 lists the altqConfig queue subcommands and the arguments they take.

Table 19-4 altqConfig queue Subcommands

Subcommand Arguments Description

add N/A Creates (adds) a new queue. The following command


creates a new queue called tcpQ:
altqConfig "queue tcpQ add"

remove N/A Deletes (removes) a queue from ALTQ. The following


command deletes the queue tcpQ:
altqConfig "queue tcpQ remove"

scheduler priorityq | cbq [default] Specifies the queueing discipline that applies to the
[packet-drop-option] queue designated by altqConfig queue
[class-specific_option] queue_name and optionally sets any of the following
options:

default

packet-drop-option

class-specific_option
For information about these options, see scheduler
Command Options, p.416.
The following command creates a priority queue,
PQueue1, with Random Early Detection (RED) as the
default queue on its interface:
altqConfig "queue PQueue1 priorityq
default RED"

qlist A space-separated list of For class-based queueing (CBQ), only. Lists


queue namess: subqueues of the queue specified by altqConfig
queue queue_name. For example, the following
qlist subq1 subq2 subq3 ...
command, issued on one line, creates a queue called
Queue1 and assigns it two subqueues, subqueueA
and subqueueB:
altqConfig "queue Queue1 scheduler cbq qlist
subqueueA subqueueB"

414
19 ALTQ
19.5 The altqConfig Utility

Table 19-4 altqConfig queue Subcommands (cont’d)

Subcommand Arguments Description

priority priority The priority of the specified queue. A higher number


assigns a higher priority to the queue.
For priority queueing: an
integer from 0 to 15.
For class-based queueing,
an integer from 0 to 7.

bandwidth int [%|b|Kb|Mb|Gb] For class-based queueing (CBQ), only. The amount of
bandwidth allocated to queue_name, where:
% = percentage of bandwidth allocated to a queue
b = bits per second allocated to a queue
Kb = kilobits per second
Mb = megabits per second
Gb = gigabits per second
Three commands follow. The first allocates two
megabits-per-second of bandwidth to Queue1 which
has subqueues subQ1 and subQ2. The second
command allocates 30% of Queue1’s bandwidth to
subQ1; the third command allocates Queue1’s
remaining bandwidth to subQ2:
altqConfig queue Queue1 bandwidth 2 MB
altqConfig queue subQ1 bandwidth 30%
altqConfig queue subQ2 bandwidth 70%

qlimit number_of_packets The maximum number of packets the specified queue 19


can hold.

enable N/A Enables a queue for assignment to an interface.

disable N/A Disables use of a queue after it has been enabled.

show If no queue name is entered, displays current


configuration information for all queues. This is
equivalent to the information about queues displayed
by the altqConfig "show" command (see altqConfig
"show", p.426).
If a queue name is entered, displays current
configuration information for the specified queue.

415
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

scheduler Command Options

When you use altqConfig queue queue_name scheduler to specify a scheduling


discipline for an interface, you can optionally specify any of the following
scheduler arguments:

default
Designates queue_name as the default queue for its interface. One queue on
every ALTQ interface must be designated as the default queue. If a packet is
sent to the interface, but does not match any ruleset requirements for of the
interface’s queues, it is assigned to the default queue. This can happen when,
for example, there is a firewall ruleset that assigns the packet to the interface,
but no ALTQ rule that assigns the packet to an ALTQ queue.
■ packet-drop-option:
One of the following options that applies to packet dropping:
– RED (see 19.2.3 Random Early Detection (RED), p.403)
– ECN (see 19.2.4 Explicit Congestion Notification (ECN), p.404)
■ class-specific_option: An option that is specific to a particular queueing
discipline. For the current release, the only option available is borrow (CBQ,
only), which specifies that the queue can borrow bandwidth from its parent
queue.
The following command creates the queue tcpQ and specifies that it is a
class-based queue that uses ECN and can borrow bandwidth from its parent
queue:
altqConfig "queue tcpQ scheduler cbq ecn borrow"

19.5.4 The altqConfig altqif Command and Subcommands

Use the altqConfig altqif command with the name of an interface to configure an
interface for ALTQ or to display information about an individual interface. The
form of the command is:
altqConfig “altqif if_name subcommand1[, subcommand2[, subcommand3[, ...]]”
Note that the portion of the command following altqConfig must be enclosed in
quotes.

416
19 ALTQ
19.5 The altqConfig Utility

Subcommands can be given in any order, following if_name. The following


altqConfig altqif command configures interface fei1 to handle queues with
priority queueing:
altqConfig altqif fei1 scheduler priorityq
In addition to the altqConfig altqif commands that specify an interface name,
there are two altqConfig altqif commands that do not take an interface name and
display configuration information about all interfaces:
altqConfig "altqif"
altqConfig "altqif show"
These commands are equivalent to each other and display the same configuration
information for interfaces that the altqConfig and altqConfig show commands do
(see 19.7.3 Sample Output from altqConfig, p.426).
The altqConfig altqif subcommands and the arguments they take are listed in the
following table.

Table 19-5 altqConfig altqif Subcommands

Subcommand Arguements Description

add N/A Adds an interface to ALTQ’s table of available


interfaces. The following command adds the interface
fei1 to the table:
altqConfig altqif fei1 add

remove N/A Deletes (removes) an interfaces from ALTQ’s table of


available interfaces.
19
scheduler priorityq | cbq Specifies the queueing discipline that can be used with
the interface designated by altqConfig altqif if_name.
The following command specifies that the interface
fei1 takes class-based queues.
altqConfig altqif fei1 scheduler cbq

qlist A space-separated list of For class-based queueing (CBQ), only. Lists child
queue names: subqueues of the root queue on the specified interface.
The following command, issued on one line, assigns
qlist q1 q2 q3 ...
subqueues, subQ1 and subqueue subQ2 to the root
queue on interface fei1:
altqConfig altqif qlist subQ1, subQ2

417
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

Table 19-5 altqConfig altqif Subcommands (cont’d)

Subcommand Arguements Description

bandwidth int [%|b|Kb|Mb|Gb] For class-based queueing (CBQ), only. The amount of
bandwidth allocated to if_name, where:
% = percentage of available bandwidth allocated to the
interface
b = bits per second allocated to a queue
Kb = kilobits per second
Mb = megabits per second
Gb = gigabits per second

qlimit number_of_packets The maximum number of packets that can be queued


at the specified interface?

tbrsize token_bucket_size The size, in bytes, of the token bucket used to regulate
the sending of packets from the specified interface. For
information about token buckets, see 19.2.5 Token
Bucket Regulator, p.404.

enable N/A Enables the specified interface for use with ALTQ. Use
this subcommand only after assigning one or more
queues to the interface.

disable N/A Disables ALTQ on an interface after it has been


enabled.

show [stat] If no interface name is entered, altqConfig "altqif


show" displays current configuration information for
all interfaces. This is equivalent to the information
about interfaces displayed by the altqConfig "show"
command (see altqConfig "show", p.426).
In an interface name is entered without the stat
argument, displays configuration information about
the specified interface.
The stat argument is used only when an interface name
is specified. It displays usage statistic for queues
associated with the specified interface. For sample
output, see altqConfig "altqif if_name show stat" for CBQ,
p.427 and altqConfig "altqif if_name show stat" for
Priority Queueing, p.428.

418
19 ALTQ
19.6 Rules and Rule Groups for Assigning Packets to Queues

19.6 Rules and Rule Groups for Assigning Packets to Queues


Wind River Firewall provides a number of routines that allow you to specify a
series of requirements that a packet must meet in order to be accepted for passage
through the Firewall. Each requirement corresponds to a rule. In Firewall, a series
of rules leading to acceptance or rejection of a packet is a rule group. Firewall rules
allow you to test, or filter, packets based on such characteristics as:
Source or destination IP address
Protocol (for example, TCP, SCTP, DNS, UDP)
TCP and UDP port and other parameters
IPv6 flow label
ICMP/ICMPv6 type and code
Packet rate
A Firewall rule group always applies to a specific interface.
For information about rules and rule groups in Wind River Firewall, see
Wind River Firewall and NAT Programmer’s Guide.
To assign a packet to an ALTQ queue, you define a Firewall rule group that
specifies an individual interface and gives the filter requirements for being
assigned to a particular queue on the interface. You then add an ALTQ-specific rule
that assigns packets that meet the requirements to a specific queue. The
ALTQ-specific rule for assigning packets to a queue has the form:
fwRuleFieldSet(pRule, FW_FIELD_ALTQ, "queue_name")
where:
pRule points to the ID of the filter rules for the current rule group
19
FW_FIELD_ALTQ is a constant that identifies the rule group as applying to
ALTQ.
queue_name is the name of the ALTQ queue to which accepted packets are
assigned. queue_name must be enclosed in quotes.
The following example gives sequence of commands that assigns outgoing TCP
packets to ALTQ Queue1 on interface motfcc2. The macros used in the individual
routines are defined in fwLib.h. For additional examples, see 19.7 Examples, p.420
1. Create a rule group that applies to forwarded outgoing packets:
pGroupId = fwRuleGroupCreate(FW_OUT_LOC, NULL, 0)

2. Specify the interface that the rule group applies to:


fwRuleFieldSet(pGroupId, FW_FIELD_NETIF, 0, 0, “motfcc2”, 0)

419
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

3. Create a rule ID for referencing the filter rules:


pRule = fwRuleCreate(pGroupId):

4. Set the rules to apply to TCP packets:


fwRuleFieldSet(pRule, FW_FIELD_TCP, 0,0,0,0,0,0,0)

5. Set the action field to accept packets that meet the preceding rules (outgoing
TCP packets):
fwRuleFieldSet(pRule,FW_FIELD_ACTION,FW_ACCEPT)

6. Apply the rules to ALTQ Queue1:


fwRuleFieldSet(pRule, FW_FIELD_ALTQ,”Queue1”)

19.7 Examples
This section provides two sets of examples of how to use altqConfig to set up
class-based and priority queueing and how to define rule groups for assigning
packets to these queues. The examples are based on two departments, Engineering
and Sales, in a fictional softwaree company. The Engineering department is made
up of three subgroups: Developent (Dev), Test, Docs.
The first set of examples is for setting up class-based queueing on an interface, the
second set is for priority queueing.

19.7.1 Class-Based Queueing Examples

In this set of examples, class-based queueing is used to set up queues for


individual departments and departmental subgroups within the fictional software
company. The Engineering department has three subgroups. Correspondingly, a
queue for Engineering is defined with three subqueues. A separate queue is
defined for the Sales department. One additional queue is defined to represent
other users of the network that may send packets to the interface used for
class-based queueing. Figure 19-4 illustrates the way the queues are structured.

420
19 ALTQ
19.7 Examples

Figure 19-4 Class-based queueing hierarchy

Root queue

Eng Sales Other

Dev Test Docs

When class-based queueing is used on an interface, each queue is assigned some


part of the total bandwidth allocated to the interface. In the current example,
bandwidth is allocated to queues based on expected network usage, with
Engineering using the most bandwidth, followed by Sales and Other.
In addition to bandwidth, class-based queues have a priority. The default priority
for a queue is 1. In the current example, all queues except Sales have the default
priority. Sales, although it sends out fewer packets and has a lower bandwidth than
Engineering, is given a priority of 4.

Table 19-6 Information Used in Defining Class-Based Queues and Filter Rules

Network usage
Department IP-address range (% of parent queue’s bandwidth) Priority

Engineering 10.10.1.3- 80 1
10.10.1.82 19
Dev 10.10.1.3- 50 1
10.10.1.52

Test 10.10.1.53- 25 1
10.10.1.77

Docs 10.10.1.78- 25 1
10.10.1.82

Sales 10.10.1.103- 15 4
10.10.1.142

Other [Any] 5 1
(with barrowing)

421
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

Class-based queues can be configured to “borrow” bandwidth (see Borrowing


Bandwidth, p.403). The queue for Other, although it is allocated only 5% of total
bandwidth, is configured so that it can borrow extra bandwidth when it is
available.
Once queues have been defined, a rule group and rules can be defined for
assigning packets to queues. In the following examples, TCP packets are assigned
to queues on the basis of the IP addresses from which they are sent.
Table 19-6 summarizes the information used to define queues and create rule
groups.

Using altqConfig to Set Up CBQ Queues

The following steps use the altqConfig utility to set up class-based queueing for
the departments and groups described in the previous section.
1. Configure an interface—in this case, fei1—for ALTQ; allocate 100% of the
bandwidth available at the interface to ALTQ:
altqConfig "altqif fei1 add bandwidth 100% scheduler cbq"

2. Add queues for Eng, Sales and Other to the interface:


altqConfig "altqif fei1 qlist Eng Sales Other"

3. Assign the Eng queue 80% of the bandwidth at the interface and give it three
child queues: dev, test, and doc:
altqConfig "queue Eng bandwidth 80% qlist dev test doc"

4. Assign bandwidth to the child queues of Eng and enable them.


altqConfig "queue dev bandwidth 50% enable"
altqConfig "queue test bandwidth 25% enable"
altqConfig "queue doc bandwidth 25% enable"

5. Now that its child queues have been enabled, you can enable Eng:
altqConfig "queue Eng enable"

6. Configure and enable Sales, assigning it a bandwidth of 15% and a priority


of 4:
altqConfig "queue Sales bandwidth 15% priority 4 enable"

7. Configure Other with a bandwidth of 5 %, make it the default queue, and


enable it:
altqConfig "queue Other bandwidth 5%"
altqConfig "queue Other scheduler cbq default"

422
19 ALTQ
19.7 Examples

8. Now that all the queues on fei1 have been enabled, enable fei1:
altqConfig "altqif fei1 enable"

9. Turn on ALTQ:
altqConfig "altq on"

Defining Filter Rules for the CBQ Queues

The following steps define Firewall rules and rule groups for assigning packets to
the queues defined in the preceding section.
1. As a convenience, set up definitions for frequently-used constants:
fwOutLoc = 3
fwfTcp = 8
fwfAction = 13
fwfIpField = 14
fwfAltq = 20
fwaReject = 0x00000000
fwaAccept = 0x80000000
dev_SourceIpMin = "10.10.1.0"
dev_SourceIpMax = "10.10.1.49"
test_SourceIpMin = "10.10.1.50"
test_SourceIpMax = "10.10.1.74"
doc_SourceIpMin = "10.10.1.50"
doc_SourceIpMax = "10.10.1.79"
sales_SourceIpMin = "10.10.1.100"
sales_SourceIpMax = "10.10.1.140"
destinationIPMin = destinationIPMax = 0

Note that there are maximum and minimum source IP addresses for each of
the queues, except Other. These values are needed for filtering packets based
on their sources. The Firewall routine used for filtering on a range of source IP 19
addresses also requires a range of destination addresses. Since destination
addresses are not used in the current example, they are set to 0.
2. Install a rule filter on output that automatically rejects all packets that are not
accepted by a user-defined rule:
fwRuleFilterInstall (fwOutLoc, fwaReject, 0, 0, 0, 0);

3. Create a rule group for outgoing TCP packets and set the action to accept so
that packets that don’t fit within the address range of any of the departmental
or subroup queues can be assigned to the default queue—Other:
cbqRuleGroup = fwRuleGroupCreate (fwOutLoc, "CBQ rules", 0);
fwRuleFieldSet (cbqRuleGroup, fwfAction, fwaAccept);
fwRuleFieldSet (cbqRuleGroup, fwfTcp , 0, 0, 0, 0, 0, 0, 0);

423
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

4. Create a rule for assigning packets to the dev queue:


devRule = fwRuleCreate (cbqRuleGroup);
fwRuleFieldSet (devRule, fwfAction, fwaAccept);
fwRuleFieldSet (devRule, fwfIpField, dev_SourceIpMin, \
dev_SourceIpMax, destinationIPMin, destinationIPMax);
fwRuleFieldSet (devRule, fwfAltq, "dev");

5. Create a rule for assigning packets to the test queue:


testRule = fwRuleCreate (fei1Grp);
fwRuleFieldSet (testRule, fwfAction, fwaAccept);
fwRuleFieldSet (devRule, fwfIpField, test_SourceIpMin, \
test_SourceIpMax, destinationIPMin, destinationIPMax);
fwRuleFieldSet (testRule, fwfAltq, "test");

6. Create a rule for assigning packets to the doc queue:


docRule = fwRuleCreate (fei1Grp);
fwRuleFieldSet (docRule, fwfAction, fwaAccept);
fwRuleFieldSet (devRule, fwfIpField, doc_SourceIpMin, \
doc_SourceIpMax, destinationIPMin, destinationIPMax);
fwRuleFieldSet (docRule, fwfAltq, "doc");

7. Create a rule for assigning packets to the Sales queue:


salesRule = fwRuleCreate (fei1Grp);
fwRuleFieldSet (salesRule, fwfAction, fwaAccept);
fwRuleFieldSet (devRule, fwfIpField, sales_SourceIpMin, \
sales_SourceIpMax, destinationIPMin, destinationIPMax);
fwRuleFieldSet (salesRule, fwfAltq, "sales");

19.7.2 Priority Queueing Examples

In this set of examples, priority queues are set up for the three subgroups under
Engineering and Sales. An additional queue—Other— is defined to represent
other users of the network that may send packets to the interface used for priority
queueing. As in the examples for class-based queueing, a rule group and rules are
defined that assign TCP packets to queues based on the IP addresses from which
they are sent.

424
19 ALTQ
19.7 Examples

Table 19-7 summarizes the information used to define queues and create rule
groups:

Table 19-7 Information Used in Defining Priority Queues and Filter Rules

Queue IP-address range Priority

Dev 10.10.1.0- 4
10.10.1.50

Test 10.10.1.51- 4
10.10.1.75

Docs 10.10.1.76- 2
10.10.1.80

Sales 10.10.1.100- 5
10.10.1.140

Other [Any] 1

Using altqConfig to Set Up Priority Queues

The following steps use the altqConfig utility to set up priority queueing for the
queues listed in Table 19-7.
1. Configure an interface—in this case, fei0—for ALTQ; allocate 100% of the
bandwidth available at the interface to ALTQ:
altqConfig "altqif fei0 add bandwidth 100% scheduler priorityq"
19
2. Add the planned queues, aside from Other, to fei0 and enable them:
altqConfig "queue dev priority 4 enable"
altqConfig "queue test priority 3 enable"
altqConfig "queue doc priority 2 enable"
altqConfig "queue sales priority 5 enable"

3. Add Other as the default queue on the interface and enable it:
altqConfig "queue Other scheduler priorityq default enable"

No priority needs to be assigned to Other, since the default priority is 1 and


that is the priority intended for Other.
4. Now that all the queues on fei0 have been enabled, enable fei0:
altqConfig "altqif fei0 enable"

425
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

5. Turn on ALTQ:
altqConfig "altq on"

Defining Filter Rules for the Priority Queues

Since the basis for assigning packets to queues is the same for both the class-based
and priority-based queues, you can the same rules. See Defining Filter Rules for the
CBQ Queues, p.423.

19.7.3 Sample Output from altqConfig

This section contains sample output from the following altqConfig commands:
■ altqConfig "show", p.426 (equivalent to altqConfig)
■ altqConfig "altqif if_name show stat" for CBQ, p.427
■ altqConfig "altqif if_name show stat" for Priority Queueing, p.428

altqConfig "show"

The altqConfig and altqConfig "show" commands are equivalent. The command
output is displayed under two headings, Interfaces and Queues. The output under
Interfaces is the same as the output for the altqConfig "altqif" and altqConfig
"altqif show" commands. The output under Queues is the same as the output for
the altqConfig "queue" and altqConfig "queue show" commands.
The following output was generated before ALTQ was turned on (altqConfig "altq
on”). That is the reason that queues and interfaces appear as disabled, not ready,
and not in use.
-> altqConfig “show”

Interfaces:
-----------
-- Queues currently in use --

No queue in use

-- User configured queues --

fei1: NotReady, qlimit=0, scheduler=cbq, TBR Disabled


Eng: Disabled; Sales: NotReady; Other: NotReady;

fei0: NotReady, qlimit=0, scheduler=priorityq,, TBR Disabled


dev1: NotReady; test1: NotReady; doc1: NotReady; Sales1: NotReady; Other1: NotReady;

426
19 ALTQ
19.7 Examples

Queues:
-------
Eng: Disabled, RefCount=1
qlimit=0, scheduler=cbq, bandwidth=80%, priority=1
Child queues: dev: NotReady test: NotReady doc: NotReady
Sales: NotReady, RefCount=1
qlimit=0, scheduler=cbq, bandwidth=0 b, priority=1
Other: NotReady, RefCount=1
qlimit=0, scheduler=cbq, bandwidth=0 b, priority=1
dev: NotReady, RefCount=1
qlimit=0, scheduler=cbq, bandwidth=0 b, priority=1
test: NotReady, RefCount=1
qlimit=0, scheduler=cbq, bandwidth=0 b, priority=1
doc: NotReady, RefCount=1
qlimit=0, scheduler=cbq, bandwidth=0 b, priority=1
dev1: NotReady, RefCount=1
qlimit=0, scheduler=priorityq,, bandwidth=0, priority=1
test1: NotReady, RefCount=1
qlimit=0, scheduler=priorityq,, bandwidth=0, priority=1
doc1: NotReady, RefCount=1
qlimit=0, scheduler=priorityq,, bandwidth=0, priority=1
Sales1: NotReady, RefCount=1
qlimit=0, scheduler=priorityq,, bandwidth=0, priority=1
Other1: NotReady, RefCount=1
qlimit=0, scheduler=priorityq,, bandwidth=0, priority=1

altqConfig "altqif if_name show stat" for CBQ

-> altqConfig "altqif fei1 show stat"

-- Queues currently in use --

queue root_fei1 bandwidth 100Mb priority 0 cbq( wrr root ) {Eng, Sales, Other}
[ pkts: 196473 bytes: 237338236 drop pkts: 0 bytes: 0 ] 19
[ qlength: 0/ 50 borrows: 0 suspends: 0 ]
[ priority: 0 depth: 2 ]
[ offtime: 1us wrr_allot: 1500b nsPerByte: 80 rate: 100Mbps ]
[ overs: 150217 overacts: 0 ]
[ AvgIdle: -73us maxidle: 3us minidle: -120us ]
queue Eng bandwidth 80Mb {dev, test, doc}
[ pkts: 0 bytes: 0 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 borrows: 0 suspends: 0 ]
queue dev bandwidth 40Mb
[ pkts: 77110 bytes: 93148880 drop pkts: 2031 bytes: 2453448 ]
[ qlength: 0/ 50 borrows: 0 suspends: 1635 ]
queue test bandwidth 20Mb
[ pkts: 39612 bytes: 47851296 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 borrows: 0 suspends: 631 ]
queue doc bandwidth 20Mb
[ pkts: 39991 bytes: 48309128 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 borrows: 0 suspends: 596 ]
queue Sales bandwidth 15Mb

427
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

[ pkts: 29886 bytes: 36102288 drop pkts: 0 bytes: 0 ]


[ qlength: 0/ 50 borrows: 0 suspends: 59 ]
queue Other bandwidth 5Mb cbq( borrow default )
[ pkts: 9874 bytes: 11926644 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 borrows: 0 suspends: 0 ]

altqConfig "altqif if_name show stat" for Priority Queueing

-> altqConfig ("altqif fei1 show stat")


-- Queues currently in use --

queue dev priority 4


[ pkts: 145920 bytes: 176271360 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]
queue test priority 3
[ pkts: 72960 bytes: 88135680 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]
queue doc priority 2
[ pkts: 72960 bytes: 88135680 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]
queue Sales priority 5
[ pkts: 54720 bytes: 66101760 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]
queue Other priq( default )
[ pkts: 18241 bytes: 22033980 drop pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]

19.8 Sample Code for Pentium Processor Machine-Clock


Routines
By default, VxWorks uses software emulation of a machine clock with ALTQ, but
you have the option of providing your own routines for initializing and reading
the machine clock used with your processor (see the entries for Machine-clock init
routine and Machine-clock read routine in Table 19-2 under 19.4.1 ALTQ Static
Configuration Parameters, p.408). For systems that use a Pentium processor, you can
base your machine-clock routines on the following sample code:
/*
* Copyright (C) 1997-2003
* Sony Computer Science Laboratories Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:

428
19 ALTQ
19.8 Sample Code for Pentium Processor Machine-Clock Routines

* 1. Redistributions of source code must retain the above copyright


* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

/*
* DESCRIPTION
*
* This module provides the sample Pentium machine dependent machine clock
* init and read routines. This module must be explicitly added to the
* BSP project (if using Workbench). If using command line build, add this
* module to the MACH_EXTRA found in the bsp's Makefile.
*
* To include these routines for ALTQ, configures the following parameters:
*
* ALTQ_USE_MACH_CLOCK: set to TRUE
* ALTQ_MACH_CLOCK_INIT_HOOK: set to init_machclk_pentium
* ALTQ_MACH_CLOCK_READ_HOOK: set to read_machclk_pentium
*
* The INCLUDE_TIMESTAMP component must also be included.
*
* NOTE:
* The rdtsc() uses the Pentium assembly language which is supported by the 19
* GNU compiler only. If using DIAB compiler, the appropriate substitution
* for rdtsc() must be implemented.
*/

#include <vxWorks.h>
#include <sys/times.h>
#include <taskLib.h>

#if defined(PRJ_BUILD)
#include "prjParams.h"
#else
#include "config.h"
#endif /* PRJ_BUILD */

#if defined (_WRS_HAS_GCC_ASM_SYNTAX)

#ifdef INCLUDE_TIMESTAMP_TSC

429
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.0

IMPORT UINT32 sysTimestampFreq (void);


IMPORT void microtime (struct timeval * pTv);
IMPORT u_int64_t (*readMachClk) (void);
extern int hz;

IMPORT u_int32_t machclk_freq;


u_int32_t machclk_per_tick;

void init_machclk_pentium(void)
{
/*
* if the clock frequency (of Pentium TSC or Alpha PCC) is
* accessible, just use it.
*/
machclk_freq = sysTimestampFreq();

#if PENTIUMPRO_TSC_FREQ == 0 /* TSC freq, 0 for auto detect */


/*
* if we don't know the clock frequency, measure it.
*/
if (machclk_freq == 0) {
struct timevaltv_start, tv_end;
u_int64_tstart, end, diff;

microtime(&tv_start);
start = (*readMachClk)();

taskDelay(hz); /* 1 sec */
microtime(&tv_end);
end = (*readMachClk)();
diff = (u_int64_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000000
+ tv_end.tv_usec - tv_start.tv_usec;
if (diff != 0)
machclk_freq = (u_int)((end - start) * 1000000 / diff);
}

machclk_per_tick = machclk_freq / hz;


#endif /* PENTIUMPRO_TSC_FREQ */
}
_WRS_INLINE u_int64_t rdtsc(void)
{
u_int64_t rv;
__asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
return (rv);
}

u_int64_t
read_machclk_pentium(void)
{
return rdtsc();
}
#endif /* INCLUDE_TIMESTAMP_TSC */

#endif /*_WRS_HAS_GCC_ASM_SYNTAX*/

430
20
Working with Device Instances

20.1 Introduction 431


20.2 Working with Network Driver Instances 432
20.3 Adding Automatic IPv4 Interface Configuration 441
20.4 Using the Reverse ARP Client 442
20.5 Working with IPv4 and IPv6 Tunneling 444
20.6 Adding a BPF Device 453

20.1 Introduction
This chapter describes how to create the following device type instances:

standard network interface devices

automatic IPv4 interface configuration

stf device instances for 6to4 tunneling

gif device instances for tunneling through an IPv4 Internet

a BPF device instance for filtering incoming packets

431
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

20.2 Working with Network Driver Instances


Although you can configure the Wind River Network Stack at build time to
automatically load, start, and configure multiple network interfaces, it is also
possible to do it manually at run-time.

NOTE: If your target system will include more than one network interface, you
may need to increase the value of the configuration parameter IP_MAX_UNITS. For
information on configuring the Wind River Network Stack to automatically start
multiple network interfaces, see Adding an END, p.473, and Adding an NPT Driver,
p.490.

To start additional network interfaces manually at run-time, complete the


following steps:
1. Use ifShow( ) to display information on each currently loaded interface. When
adding a new interface, you do not want to conflict with any interface already
loaded.
2. Use muxDevLoad( ) to load the driver for the network interface.
3. Use muxIfFuncAdd( ) to install any routines particular to the relationship
between a particular interface and a particular protocol. You can use this
routine to assign an address resolution routine, a multicast address resolution
routine, or an output routine.

NOTE: When working with the network interface drivers and tunnel devices
supplied by Wind River, this step is usually handled for you. For example, if a
driver registers as an Ethernet driver and if you do not intend to multicast
through that driver instance, you can skip this step because registering as an
Ethernet driver automatically registers arpResolve( ) as the address resolution
routine. Similarly, if you are working with either of the supplied pseudo
devices, stf or gtf, you can skip this step. It is handled automatically when the
tunnel library is initialized.

4. Use muxDevStart( ) to initialize the network interface.


5. Call the network layer’s fooAttach( ) routine to attach (bind) the driver to the
service. For example, to attach to the IPv4 stack, call ipAttach( ). To attach to
the IPv6 stack, call ip6Attach( ).
6. Configure the interface. This means assigning an IP address and a netmask
(IPv4) or prefix (IPv6). Use ifconfig( ). If you call ifconfig( ) to bring up inet6,
it triggers IPv6 link-local address generation for the interface.

432
20 Working with Device Instances
20.2 Working with Network Driver Instances

7. Use hostAdd( ) to add a host name to the host table.


8. Bring up the link state and protocol state of the interface using the up, link up,
inet6 up, and inet up options in ifconfig( ). To bring up both the link and
protocol (both IPv4 and IPv6) states, use the global up option. For example:
ifconfig "fei0 up"

To separate out each aspect of the global up shown above, you would need to
do the following:
ifconfig "fei0 link up"
ifconfig "fei0 inet up"
ifconfig "fei0 inet6 up"

If you do not want to bring up both the IPv4 and IPv6 functionality for the
interface, omit any of the above calls as needed.
9. Check that the interface was loaded and configured correctly by calling the
following:
ifShow( ) – list configuration information for network devices.
netstat( ) – check that the routing table has an entry for the device.
hostShow( ) – check that the address/hostname was added to the host table.

NOTE: For information on the exact inputs expected by the routines named above,
see the relevant reference entries.

20.2.1 Attaching a Protocol to a Network Interface

To communicate with remote peers, a protocol, such as IPv4, must attach itself to
one or more network interfaces. Attaching a protocol to an interface allows packets
addressed to that interface to flow up to the protocol. It also lets the protocol 20
transmit packets out through the interface.
If your build-time configuration includes INCLUDE_IPATTACH, the network stack
initialization code automatically attaches IPv4 to the network interface specified in
the boot parameters. Similarly, if you include INCLUDE_IP6ATTACH, IPv6 is also
attached to that network interface. For more information on these components, see
5. Configuring Transport and Network Protocols.
If your target supports more than one interface, there is no automatic attaching of
IPv4 or IPv6 to the additional interfaces. If you want to attach IPv4 or IPv6 to these
interfaces, you must call ipAttach( ) or ip6Attach( ) for each interface attachment
you want to create. If you need to remove an IPv4 attachment, call ipDetach( ). If
you need to remove an IPv6 attachment, call ip6Detach( ).

433
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

20.2.2 Configuring a Network Interface with an Address

Attaching a protocol to an interface allows packets addressed to that interface to


flow up to the protocol. You must assign an address to the interface in order for it
to know which packets are addressed to it. When assigning an address to an
interface, you also need to assign a netmask (IPv4) or prefix (IPv6). This netmask
or prefix value is used when IPv4 or IPv6 wants to determine whether a particular
network is accessible through that interface.
Previous network stacks relied on ifLib routines to set the address and mask
associated with a network interface. The ifLib routines are still supported, but for
IPv4 interfaces only. To configure an interface for IPv6, you can use the API
supplied by if6Lib. Alternatively, you can use ifconfig( ), which can handle both
IPv4 and IPv6.

Using ifconfig( )

The ifconfig( ) routine lets you assign an address and netmask or prefix to a
network interface all in one call. It also lets you retrieve configuration information
on an interface. The valid ifconfig( ) command-line syntax for assigning
information to a network interface is as follows:
-> ifconfig "interface [-flags] [protocol] [parameter parameterValue]"

For a detailed description of all possible flags and parameter values, see the
ifconfig( ) reference entry. From among the more than 20 valid parameter values,
ifconfig( ) chooses add, as the default. Thus, if you use ifconfig( ). without
specifying a parameter value, ifconfig( ) assumes add.
Whether ifconfig( ) configures an interface for IPv4 or IPv6 depends on the protocol
value you supply. For the Wind River Network Stack, the only valid protocol
values are inet, for IPv4 (the default) and inet6, for IPv6. Consider the following:
-> ifconfig "fei1 192.0.2.64"

This ifconfig( ) call configures the fei1 network interface to have an IPv4 address
of 192.0.2.64. Because no mask was specified for what would have been a class C
address pre-CIDR, the command assumes a default class B netmask value of
0xFFFFFF00. To override the default netmask associated with an IPv4 address, you
can use the CIDR slash notation. For example:
-> ifconfig "fei1 192.0.2.64/16"

This command specifies a netmask of 16 bits, or 0xFFFF0000. The netmask value is


used when the ifconfig( ) call creates an interface entry in the system route table.

434
20 Working with Device Instances
20.2 Working with Network Driver Instances

Alternatively, you can use the inet and netmask options:


-> ifconfig "fei1 inet 192.0.2.64 netmask 0xFFFF0000"

To use ifconfig( ) to configure an interface to use an IPv6 address, you need to use
the inet6 protocol value in the command explicitly. For example:
-> ifconfig "fei1 inet6 2002:C000:0240::66/16"

The ifconfig( ) call above configures the fei1 network interface to have an IPv6
address of 2002:C0000:0240:66. The “/16” indicates a prefix length of 16 bits.
Otherwise, the ifconfig( ) call would have assumed a default prefix of 64 bits.
Alternatively, you can use the inet6 and prefixlen options:
-> ifconfig "fei1 inet6 2002:C000:0240::66 prefixlen 16"

The example address shown above was chosen because it is a 6to4 IPv6 address for
192.0.2.64. The IPv4 notation uses base 10 numbers. The IPv6 notation uses
hexadecimal numbers. Thus, 192.0.2.64 is C0.0.2.40 which is C000:240.

Using the ifLib API

The ifLib API provides the ifMaskSet( ) and ifAddrSet( ) routines for configuring
a network interface for use with IPv4. As their names suggest, you use
ifMaskSet( ) to set the mask associated with the route table entry for the interface;
and you use ifAddrSet( ) set to assign an IPv4 address for the interface.
The ifLib API imposes a sequence on the use of the ifMaskSet( ) and ifAddrSet( )
calls that you make to configure an interface. The ifMaskSet( ) call must come
before the ifAddrSet( ) call. If you call ifAddrSet( ) without a previous
ifMaskSet( ) call, the ifAddrSet( ) call assumes the default pre-CIDR netmask
associated with the address you specify. Such a mask will likely be too large. This
is not necessarily a disaster, but the routing table may incorrectly indicate that it 20
has local access to addresses that actually reside on a remote network. For that
reason, you will see a lot of ARP errors and transmission failures.
For example, to assign the 192.0.2.64 IPv4 address to the fei1 interface, enter:
-> ifAddrSet "fei1", "192.0.2.64"

This call made without a prior ifMaskSet( ) call assigns 192.0.2.64 to the fei1
interface and creates a route table entry for 192.0.2.64 with a 24-bit netmask. If you
had wanted a 16-bit netmask, you would have needed to precede the ifAddrSet( )
call with an ifMaskSet( ) call. For example:
-> ifMaskSet "fei1", 0xFFFF0000
-> ifAddrSet "fei1", "192.0.2.64"

435
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

If you mistakenly call ifAddrSet( ) before you call ifMaskSet( ), you cannot fix the
mistake simply by calling ifMaskSet( ). You must delete the problematic route
entry from the route table and then call ifMaskSet( ) and ifAddrSet( ) in the
proper order. For information on how to delete route table entries, see 20.2.4 Using
routec( ) to Add or Delete Route Table Entries, p.437.

Using the if6Lib API

The if6Lib API breaks out the ifconfig( ) options for IPv6 configuration into
individually callable routines suitable for use in compiled code or from a
command line. As much as possible, the if6Lib API parallels that provided by
ifLib. For example, if6AddrAdd( ) is the if6Lib parallel to the ifLib routine,
ifAddrAdd( ).
-> if6AddrAdd "fei1", "2002:C000:0240::66 ", 16

This if6AddrAdd( ) call above configures the fei1 network interface to have an
IPv6 address of 2002:C000:0240::66, a 6to4 IPv6 address for 192.0.2.64. The prefix
length is 16 bits. For more information, see the if6Lib reference entry.

20.2.3 Editing the Route Table

If you have accidentally misconfigured a network interface, you will need to delete
the problematic entry from the route table. You may also want to edit the routing
table manually when first testing the routing stack software or a new application
that you have just written or ported for that stack. At this time, it is often
convenient to enter a default network route. In addition, setting up tunnels
through the IPv4 Internet requires some editing of the routing table, see
20.5 Working with IPv4 and IPv6 Tunneling, p.444.
For command-line editing of the route table, the stack also supports routec( ), a
port of the UNIX route( ) utility. This utility provides options for viewing the
routing table contents as well as for adding and deleting route entries.
All the APIs mentioned above are strongly oriented towards command-line use.
For a utility more appropriate to use within compiled code, use a standard routing
socket. For more information on routing socket messages, see 15. Working with
Routing Sockets.

436
20 Working with Device Instances
20.2 Working with Network Driver Instances

20.2.4 Using routec( ) to Add or Delete Route Table Entries

You can use routex( ) to add or delete route table entries for local losts and
gateways. Although the appendices to this manual include a reference entry that
describes the routec( ) utility, the following examples cover most uses of the
command. To verify the proper operation of a routec( ) command, use:
-> netstat "-r"

To add an IPv4 network route:


-> routec "add -net destination-network gateway-address -netmask netmask-value"

For example:
-> routec "add -net 192.168.10.0 192.168.1.1 -netmask 255.255.255.0"

To delete this route, replace the add with a delete.


To add an IPv6 network route:
-> routec "add -net -inet6 destination-network gateway-address%scope
-prefixlen number"

The scope value in gateway-address% scope is often most conveniently specified


using a network interface name. Using a network interface name specifies the
scope to be the local link available through that network interface.
For example:
-> routec "add -net -inet6 2001:DB8:84b1:7600::
fe80::20f:ff:fe00:101%fei0 -prefixlen 64"

To delete this route, replace the add with a delete.


To add an IPv4 host route:
-> routec "add -host host-address gateway-address"
20
For example:
-> routec "add -host 192.168.13.76 192.168.1.1"

To delete this route, replace the add with a delete.


To add an IPv6 host route:
-> routec "add -host -inet6 host-address gateway-address%scope"

For example:
-> routec "add -host -inet6 2001:DB8:84b1:7600:0205:00ff:fe00:0101
fe80::20f:ff:fe00:101%fei0"

To delete this route, replace the add with a delete.

437
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

To add a default IPv4 route:


-> routec "add default IPv4-gateway-address"

For example:
-> routec "add default 192.168.1.1"

To delete this route, replace the add with a delete.


To add a default IPv6 route:
-> routec "add -inet6 default IPv6-gateway-address%scope"

For example:
-> routec "add -inet6 default fe80::20f:ff:fe00:101%fei0"

To delete this route, replace the add with a delete.

20.2.5 Fixing Interfaces that Have Erroneous Addresses

A call to ifAddrSet( ) or ifconfig( ) automatically creates a local entry in the


routing table. Local entries in the routing table identify network interfaces on the
local host. If you did not assign the correct address to the interface or if you forgot
to call ifMaskSet( ) before calling ifAddrSet( ), you need to delete the local host
table entry and then reconfigure the interface.
To reconfigure a network interface when working with the ifLib API:
-> routec "-n delete routeDestinationValue routeGatewayValue"
-> ifMaskSet "nameOfNetworkInterface", "newMaskValueForNetwork"
-> ifAddrSet "nameOfNetworkInterface", "newIPaddressForNetworkInterface"

If you are working with the ifconfig( ) interface, replace the ifMaskSet( ) and
ifAddrSet( ) calls with the appropriate ifconfig( ) call:
-> ifconfig "interface inet6 newIPv6address prefixlen newPrefixLengthValue" (for IPv6)
-> ifconfig "interface inet newIPv4address netmask newMaskValue" (for IPv4)

Alternatively, you can use the slash notation to specify the address and netmask
(or prefix length) in one string:
-> ifconfig "interface inet6 newIPv6address/newPrefixLengthValue" (for IPv6)
-> ifconfig "interface inet newIPv4address/newMaskValue" (for IPv4)

For more information, see Using ifconfig( ), p.434.

438
20 Working with Device Instances
20.2 Working with Network Driver Instances

20.2.6 Assigning a Host Name to an Address

It is often easier to refer to hosts and interfaces by names instead of by IP addresses.


To add host names to the local host table, call hostAdd( ). For example:
-> hostAdd "myIPv4Interface", "192.0.2.64"
-> hostAdd "myIPv6Interface", "2002:C0000:240::66"

The host table stores one entry per Internet address, but you can associate multiple
names with an address. The additional host names are added as aliases.
When specifying IPv6 link or site local addresses, you must supply a scope
delimiter, %, and corresponding interface ID. For more information, see the
hostAdd( ) reference entry.

20.2.7 Configuring IPv4 Broadcast Addresses

Many physical networks support the notion of broadcasting a packet to all hosts
on the network. A special Internet broadcast address is interpreted by the network
subsystem to mean “all systems” when specified as the destination address of a
datagram message (UDP). 1
Unfortunately, there is ambiguity concerning which address is the broadcast
address. The Internet specification now states that the broadcast address is an
Internet address with a host part of all ones (1). Some older systems use an Internet
address with a host part of all zeros as the broadcast address.
Most new network stacks, including the Wind River Network Stack, accept either
address on incoming packets as being a broadcast packet. When an application
sends a broadcast packet, it must use the correct broadcast address for its system.
The Wind River Network Stack normally uses a host part of all ones as the
20
broadcast address. Thus, a datagram sent to Internet address 10.255.255.255
(0x0AFFFFFF) is broadcast to all systems on network 10. To allow compatibility
with other systems, the Wind River Network Stack allows the broadcast address
to be reassigned for each network interface by calling the routine ifBroadcastSet( ).
For more information, see the reference entry for ifBroadcastSet( ).
In addition, the Wind River Network Stack supports multicasting – transmission
to a subset of hosts on the network. For more information on multicasting, see
13.2.2 Using a Datagram (UDP) Socket to Access IPv4 Multicasting, p.260.

1. IPv6 does not support broadcast messages. This is an IPv4 concept only.

439
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

20.2.8 Bringing the Device Up for Link and Protocol Communication

As mentioned in the procedure on page 433, starting and enabling a network


interface requires that you use ifconfig( ) to bring up both the link and protocol
state of the device. Bringing these states up or down gives you a software-based
mechanism that you can use to start or stop transmission over the device. This
functionality also lets you independently stop IPv4 and IPv6 transmission on a
single interface.
The link state is controlled by the link option to ifconfig( ). While the link state is
down, the device will accept no additional packets from the link layer. You bring
the link state up or down using the up and down options to ifconfig( ).
For example:
-> ifconfig "fei0 link down"
-> ifconfig "fei0 link up"

Similarly, you control the IPv4 and IPv6 functionality of the device using the inet
and inet6 options in an ifconfig( ) call. These options also take the up and down
modifiers. For example:
-> ifconfig "fei0 inet down"
-> ifconfig "fei0 inet6 down"
-> ifconfig "fei0 inet up"
-> ifconfig "fei0 inet6 up"

To bring up the link and IPv4 and IPv6 functionality all at once, you can use the up
modifier without specifying link or inet or inet6. For example:
-> ifconfig "fei0 up"

Similarly, to bring down the link or IPv4 or IPv6 functionality all at once, you can
use the down modifier without specifying link or inet or inet6. For example:
-> ifconfig "fei0 down"

20.2.9 Configuring Router Advertisement and Solicitation for an Interface

By calling rtadvConfig( ), you can control which prefixes are advertised though a
particular interface. You cannot pause and enable the Router Advertisement or
Router Solicitation functionality on a per-interface basis. For information on how
to do this, see the rtadvConfig( ) reference entry.
For information on starting and stopping the Router Solicitation task, see the
rtsolStart( ) and rtsolStop( ) reference entries.

440
20 Working with Device Instances
20.3 Adding Automatic IPv4 Interface Configuration

For information on starting the Router Advertisement task, see the rtadv( )
reference entry. There is no publicly callable routine that you can use to stop the
Router Advertisement task. Router advertisement is a router (not host) feature. It
requires that IPv6 packet forwarding be enabled. You can enable IPv6 forwarding
as follows:
-> Sysctl "net.inet6.ip6.forwarding=1"

If you disable forwarding, you effectively pause router advertisement until you
turn on forwarding for IPv6.

20.3 Adding Automatic IPv4 Interface Configuration


Using IPv4 auto configuration, hosts can join a local network automatically
without resorting to manual configuration or hard coded IPv4 addresses. In
addition, if an agent later assigns a routable IPv4 address to the interface, the target
uses that address instead of the auto configured address. The auto configured
address is retained, defended, and usable if the routable IPv4 address is removed.

Configuring VxWorks for Auto IP

The Wind River Network Stack supports automatic IPv4 interface configuration.
To add support for this feature, include the Auto IPv4 Address Configuration
component in your VxWorks image. This component is listed under the
Network Components > Network Applications folder in Workbench.
20
The INCLUDE_AIP component pulls in aipLib, a library that allows a target to
automatically configure an interface with a link-local IPv4 address. Including
INCLUDE_AIP in a VxWorks image sets up a call to the usrNetAutoIpInit( )
initialization routine, which is defined in the net/coreip/apps/usrNetAutoipCfg.c
file.
This component requires the following configuration components, which are
automatically included:

INCLUDE_IPV4

INCLUDE_BPF
■ INCLUDE_ARP_API

INCLUDE_SELECT

441
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Using Auto IP

Auto IP chooses an address at random from the 169.254/16 IPv4 address space.
The target then uses ARP requests to verify that the address is not already in use
on the local link. If the address is in use, another address is chosen from the
169.254/16 IPv4 address space. This process is repeated until an unused address is
found.
Using this address, the target can communicate with other IPv4 targets on the local
link, although the address is not suitable for communication beyond the local link.
Superficially, IPv4 auto configuration is similar to IPv6 auto configuration, and can
be used in much the same way. For example, one environment well suited to IPv4
auto configuration is an isolated IPv4 network of devices without access to a
DHCP server.

NOTE: Auto IP can configure only one interface on a target, even if


multiple interfaces exist.

20.4 Using the Reverse ARP Client


The Wind River Network Stack supports the reverse ARP client.

Configuring VxWorks for RARP Support

To add support for this feature, include the Reverse ARP Client component in
your VxWorks image. This component is listed under the
Network Components > Network Protocol Components >
Network IPv4 Components folder in Workbench.
The INCLUDE_RARP component pulls in rarpLib, a library that provides an
implementation of the Reverse Address Resolution Protocol (RARP) client that
conforms to RFC 903. Including INCLUDE_RARP in a VxWorks image sets up a call
to the usrNetRarpInit( ) initialization routine, which is defined in
net/coreip/usrNetRarpCfg.c.

442
20 Working with Device Instances
20.4 Using the Reverse ARP Client

This component supports the following configuration parameter:


RARP_DEBUG

Synopsis: Enable the RARP debug facility.


Default: FALSE

Using the RARP Client

Using the RARP client, a VxWorks target can broadcast a RARP request packet
containing its hardware address. If there is a RARP server on the local network, it
responds with a RARP response packet. This packet contains the IP address that
the RARP host associates with the hardware address in the RARP request packet.
Diskless workstations sometimes use RARP at boot time to request an IP address.
If you are writing boot code for a device that requires an external source to supply
more than an IP address, consider using BOOTP or DHCP.
For more information on the Wind River Network Stack RARP client, see the
rarpLib reference entry.

NOTE: RARP is an older protocol that, for most purposes, is now superseded by
BOOTP, which is largely superseded by DHCP.

Using the RARP Client to Get an IP Address

To use the RARP client to get an IP address for a network interface, call rarpGet( ).
As input, this routine expects the name and unit number of the local network
interface for which you want to request an IP address. This routine also expects a
timeout value as well as a pointer to a structure into which it can write the IP
address if the call is successful. A rarpGet( ) call does not execute asynchronously. 20
Control does not return from rarpGet( ) until a RARP host supplies the address or
the timeout expires. For more information, see the rarpGet( ) reference entry.

Generating RARP Client Debug Messages

By default, the RARP client does not generate debug messages. You can use
rarpDebugSet( ) to activate the RARP client debug facility. While active, this
facility sends debug messages to the logging task. For more information, see the
rarpDebugSet( ) reference entry.

443
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

20.5 Working with IPv4 and IPv6 Tunneling


In this document, tunnelling through an IPv4 Internet refers to the encapsulation
of data (such as an IPv4 or an IPv6 packet for a VPN connection) in an IPv4 packet
that is then transmitted to an IPv4-addressed destination. At the destination, the
data is retrieved from the IPv4 packet and processed. If the data retrieved is an
IPv6 packet, and the receiving stack is a dual IPv4/IPv6 stack, the stack can
forward the IPv6 packet out onto the IPv6 Internet.

NOTE: Although this chapter focuses on host-to-host tunnels, one can also set up
set up host-to-router tunnels, router-to-router tunnels, and all such permutations.

20.5.1 Configuring VxWorks for Tunneling

The Wind River Network Stack supports the following gif and stf pseudo device
tunneling configuration components:
■ GIF Tunnel Interface Driver
■ 6to4 Tunnel Interface Driver
These components are all listed under the
Network Components > Network Applications folder in Workbench. d

GIF Tunnel Interface Driver

The INCLUDE_GIF component pulls in modules that implement the gif pseudo
tunneling device used with IPv4. This component has no configuration
parameters.

6to4 Tunnel Interface Driver

The INCLUDE_STF component pull in support for the 6to4 pseudo tunneling
device used with IPv6. This component requires the INCLUDE_IPV6 component
and has no configuration parameters.

444
20 Working with Device Instances
20.5 Working with IPv4 and IPv6 Tunneling

20.5.2 Using Tunneling Devices

Using the stf and gif pseudo devices, it is possible to create 6to4 (stf) and RFC
2893-style (gif) tunnels.
The gif-based tunnels use a tunnel style sometimes described as configured
tunnels because you must specify the addresses of the endpoints at set up time.
These tunnels are essentially point-to-point links. To tunnel IPv6 traffic, these
gif-based tunnels require both tunnel ends to be dual IPv4/IPv6 nodes. They do
not require that you identify the tunnel endpoints in terms of 6to4 IPv6 addresses.
This is because the IPv4 addresses associated with the tunnels are configured into
the gif device instance when it is first loaded. Thus, you are free to configure the
tunnel endpoints using whatever IPv6 addresses are most appropriate.

Figure 20-1 Tunnel Send Path

stf0 gif0 gif1 gif2

TCP UDP TCP UDP tunnelLib

IPv6 IPv4

MUX
etherOutput tunnelIfOutput 20

Eth0 Eth1 stf0 gif0 gif1 gif2

NOTE: For gif, only 6-in-4 tunnels are supported. Thus, 4-in-6, 4-in-4 and 6-in-6
tunnels are not supported for gif.

445
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The stf-based tunnels are one of the many tunnel-styles sometimes described as
automatic tunnels. Despite their name, automatic tunnels do require some
minimal configuration work. What is not explicitly configured is the endpoint of
the tunnel. That information is taken from the destination address of the packet,
which is possible because stf devices automatically tunnel to 6to4 IPv6 addresses
only. If you make appropriate entries in the route table, you can tunnel other IPv6
traffic through the stf tunnel for routing by the dual stack at the other end, but only
packets with IPv6 6to4 addresses are automatically tunneled.
Automatic tunnels are described below. Configured tunnels are described in
20.5.4 Using gif Devices to Create RFC 2893-Style Configured Tunnels, p.449.

Figure 20-2 Tunnel Receive Path

stf0 gif0 gif1 gif2

TCP UDP TCP UDP tunnelLib

IPv6 IPv4

MUX

Eth0 Eth1 stf0 gif0 gif1 gif2

NOTE: For gif, only 6-in-4 tunnels are supported. Thus, 4-in-6, 4-in-4 and 6-in-6
tunnels are not supported for gif.

446
20 Working with Device Instances
20.5 Working with IPv4 and IPv6 Tunneling

20.5.3 Using stf Devices to Create 6to4 Tunnels for IPv6 Packets

On a Wind River Network Stack dual stack, the creation of a 6to4 tunnel requires
that you create an stf pseudo device to encapsulate the IPv6 packets. After creating
the stf, you must create entries in the route table so that remotely destined (not link
local) IPv6 packets are directed to this pseudo device.

Figure 20-3 6to4 Addresses

2002 IPv4 Address SLA ID Interface ID

16 bits 32 bits 16 bits 64 bits

Consider the following set up code for automatic tunneling on a Wind River
Network Stack dual stack.
/*******************************************************************************/
/* code for STF tunnel setup */

#include "vxWorks.h"
#include "m2Lib.h"
#include "muxLib.h"
#include "ipProto.h"
#include "net/utils/ifconfig.h"
#include "net/utils/routeCmd.h"
#include "net/ethernet.h"

extern END_OBJ * stfLoad (char * initString, void * pBsp);

void stfTest ()
{
void * pCookie;
pCookie = muxDevLoad (0, stfLoad, "0:1:0:0:0", 0, 0);
if (pCookie == NULL)
{ 20
printf ("muxDevLoad failed.\n");
return;
}

muxDevStart (pCookie);
ip6Attach (0, "stf");
tunnelIfConfig ("stf0", AF_INET, "IPv4AddressForLocalInterface", NULL);
ifconfig ("stf0 inet6 6to4AddressForLocalInterface prefixlen 128");
routec ("add -inet6 2002:: 6to4AddressForLocalInterface -prefixlen 16");
}

447
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

From the command line, and, assuming a local interface with an IPv4 address of
192.0.2.1, you could set up an stf tunnel as follows:
-> ifconfig "fei1 192.0.2.1"
-> pcookie = muxDevLoad ( 0, stfLoad, "0:1:0:0:0", 0, 0 )
-> muxDevStart pcookie
-> ip6Attach 0, "stf"
-> tunnelIfConfig ("stf0", AF_INET, "192.0.2.1", NULL)
-> ifconfig "fei0 inet6 2002:C000:0201::66 prefixlen 48"
-> ifconfig "stf0 inet6 2002:C000:0201::66 prefixlen 128"
-> routec "add -inet6 2002:: 2002:C000:0201::66 -prefixlen 16"
-> routec "add default 192.0.2.1"

The muxDevLoad( ) call creates the stf device instance.


The call to muxDevStart( ) actually starts the stf device instance. This device can
accept IPv6 packets addressed to 6to4 destinations, encapsulate them within IPv4
packets, and then queue the packets for transmission to the IPv4 address
embedded in the 6to4 address.2
The ip6Attach( ) call binds IPv6 to the stf device.
The tunnelIfConfig( ) call configures the tunnel associated with stf0 to carry
packets through an IPv4 address space, AF_INET, using the local IPv4 interface
with the address, 192.0.2.1. Because this tunnelIfConfig( ) call is for an stf device,
the destination address is NULL.
The three ifconfig( ) calls configure three network interfaces: fei1, the default
interface for IPv4; fei0, for IPv6 destinations on the local link; and stf0, for IPv6
access to remote IPv6 networks. These ifconfig( ) calls also add interface entries to
the route table.
The ifconfig( ) for fei0 creates a route table entry that catches packets with IPv6
destinations that match the first 48 bits of the 2002:C000:0201::66, which happens
to be 2002:C000:0201. This is the IPv4 address of the local network interface
prefixed with an IPv6 6to4 prefix. This 6to4 IPv6 address implies a local IPv6
address space of 80 bits. By convention, the 16 bits just after the IPv4 segment of
the address are interpreted as a Site-Level Aggregation (SLA) ID, which you can
use to organize the local space into subnets. This is a very large space, and the
addresses within it are addressable from outside the local site.
The ifconfig( ) for stf0 creates a route entry that matches all packets destined
exactly for 2002:C000:0201::66. This is not immediately useful, but it is followed
immediately by the routec( ) call:
-> routec "add -inet6 2002:: 2002:C000:0201::66 -prefixlen 16"

2. For information on the third parameter in the muxDevLoad( ) call, see the description of
stfLoad( ) provided in the reference entry for stf.

448
20 Working with Device Instances
20.5 Working with IPv4 and IPv6 Tunneling

This routec( ) call creates a route that directs packets with 6to4 addresses to
2002:C000:0201::66, which is also known as stf0.
Because ifconfig( ) for fei0 already created a route that matches better on local 6to4
addresses, this 2002::/16 route catches all packets destined to remote 6to4
addresses. The packets headed to these addresses are directed to stf0, which
encapsulates them in IPv4 packets and then transmits them using the default
interface for IPv4, fei1.
For example, consider a ping6( ) to 2002:C000:0202::33. This IPv6 destination
would not match on the fei0 route entry for local IPv6 hosts, so it would be
directed to stf0. This pseudo device would then encapsulate the IPv6 packet in an
IPv4 packet destined for 192.0.2.2.
To send packets to native IPv6 addresses, you could contract with an IPv6 router
with 6to4 addresses to relay your packets. You would then need to update your
routing table to forward your IPv6 packets to this router. For example:
-> routec "add -inet6 default 2002:C0000:0203::1"

This call would create a default route entry that forwarded IPv6 packets to the IPv6
router at 192.0.2.3. Make sure that you keep your normal 6to4 route to 2002::/16 to
ensure that this gateway is not used for all 6to4 packets as well. This helps to
ensure that the best route is taken for normal 6to4 traffic.
If you intend that the systems at the tunnel ends function as routers, make sure that
the network stack at those tunnel ends are configured to forward IPv6 packets. If
the stack is a VxWorks network stack, you can use Sysctl( ):
-> Sysctl "net.inet6.ip6.forwarding=1"

20.5.4 Using gif Devices to Create RFC 2893-Style Configured Tunnels


20
The RFC 2893-style configured tunnels based on gif devices are point-to-point
links. They are similar to point-to-point links over a serial cable except the
transmission medium happens to be the Internet. Through the mediation of a gif
device instance, you can use a configured tunnel as a direct connection to an
endpoint in the IPv6 address space. Unlike stf-based tunnels, the tunnel endpoints
need not be defined in terms of 6to4 IP addresses. Both endpoints need to support
dual IPv4/IPv6 stacks, and both tunnel endpoints need an IPv4 address in
addition to whatever IPv6 addresses you associate with the tunnel endpoints.
Setting up a gif-base configured tunnel is much like setting up an stf-based
automatic tunnel. To create a gif device instance and bind it to the IPv6 stack, use
code modelled after the following:

449
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

/* code for configuring a gif tunnel */


#include "vxWorks.h"
#include "m2Lib.h"
#include "muxLib.h"
#include "ipProto.h"
#include "net/utils/ifconfig.h"
#include "net/utils/routeCmd.h"
#include "net/ethernet.h"

extern END_OBJ * gifLoad (char * initString, void * pBsp);

void gifTest ()
{
void * pCookie;

pCookie = muxDevLoad (0, gifLoad, "1:0:0:0", 0, 0);


if (pCookie == NULL)
{
printf ("muxDevLoad failed!\n");
return;
}

muxDevStart (pCookie);
ip6Attach (0, "gif");
tunnelIfConfig ("gif0", AF_INET, "sourceIPv4Address", "destinationIPv4Address");

ifconfig ("gif0 inet6 localIPv6Address remoteIPv6Address prefixlen 128");


}

Packets sent to this gif device are always transmitted from the specified local
interface to the specified remote interface. In the code above, the tunnelIfConfig( )
call specifies AF_INET as its address family. This indicates a tunnel is through an
IPv4 address space. Thus, the source and destination addresses are IPv4 addresses.
If the address family were AF_INET6, it would indicate a tunnel through the IPv6
address space, which would require IPv6 source and destination addresses in the
tunnelIfConfig( ).
Now that you have created a device to manage the tunnel, you need to add
configuration information that associates IPv6 addresses with the tunnel
endpoints. To do this, call ifconfig( ) as follows:
-> ifconfig "gif0 inet6 localIPv6Address remoteIPv6Address prefixlen 128"

Note that the IPv6 addresses supplied above need not be 6to4 addresses. They can
be any valid IPv6 addresses (of proper scope) validly associated with the tunnel
endpoints.
To direct IPv6 packets to this device by default, you can add an IPv6 default entry
to the route table. For example:
-> routec "add -inet6 default tunnelEndpointIPv6Address"

450
20 Working with Device Instances
20.5 Working with IPv4 and IPv6 Tunneling

Alternatively, you can direct only some IPv6 packets to the interface. For example,
the following entry would capture traffic destined for 2001:DB8:1::/64:
-> routec "add -inet6 2001:DB8:1:: tunnelEndpointIPv6Address -prefixlen 64"

An Example Configuration

Assume that you own the IPv4 address 10.1.0.1 and the IPv6 address
2001:DB8:1234::1. Assume also that the owner of IPv4 address 10.2.0.1 has agreed
to route your IPv6 traffic for 2001:DB8:3333::/32 and that the IPv4 node at 10.2.0.1
is a dual IPv4/IPv6 stack with an IPv6 address of 2001:DB8:5678::1. You can:
-> pcookie = muxDevLoad ( 0, gifLoad, "1:0:0:0", 0, 0 )
-> muxDevStart pcookie
-> ip6Attach 0, "gif"
-> tunnelIfConfig "gif0", AF_INET, "10.1.0.1", "10.2.0.1"

Then you would configure the interfaces and route table as follows:
-> ifconfig "fei0 inet6 2001:DB8:1234::1"
-> ifconfig "gif0 inet6 2001:DB8:1234::1 2001:DB8:5678::1 prefixlen 128"
-> routec "add -inet6 2001:DB8:3333:: 2001:DB8:5678::1 -prefixlen 48"

Your local node now supports the following devices and route table entries:
Addresses:

fei0 10.1.0.1
fei0 2001:DB8:1234::1
gif0 2001:DB8:1234::1 -> 2001:DB8:5678::1 (and configured from
10.1.0.1 to 10.2.0.1)

Routes:

10.1.0.1/8 fei0
2001:DB8:1234::/64 fei0
2001:DB8:3333::/32 gif0

If you have negotiated for routing services from more than one remote IPv6 router 20
that supports a dual IPv4/IPv6 stack, you can create additional gif devices to
manage configured tunnels through those routers. You would also want to set up
your route table to control which IPv6 packets went to which router.
For example, if the second remote dual IPv4/IPv6 stack was at 10.3.0.1 IPv4 and
2001:DB8:9999::1 IPv6, you would use the following set up code:
-> pcookie0 = muxDevLoad ( 0, gifLoad, "1:0:0:0", 0, 0 )
-> pcookie1 = muxDevLoad ( 1, gifLoad, "1:0:0:0", 0, 0 )
-> muxDevStart pcookie0
-> muxDevStart pcookie1
-> ip6Attach 0, "gif"
-> ip6Attach 1, "gif"
-> tunnelIfConfig "gif0", AF_INET, "10.1.0.1", "10.2.0.1"
-> tunnelIfConfig "gif1", AF_INET, "10.1.0.1", "10.3.0.1"

451
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

-> ifconfig "fei0 inet6 2001:DB8:1234::1"


-> ifconfig "gif0 inet6 2001:DB8:1234::1 prefixlen 128"
-> ifconfig "gif1 inet6 2001:DB8:1234::1 prefixlen 128"

This sets up the following devices:


gif0 2001:DB8:1234::1 -> 2001:DB8:5678::1 (Configured 10.1.0.1 -> 10.2.0.1)
gif1 2001:DB8:1234::1 -> 2001:DB8:9999::1 (Configured 10.1.0.1 -> 10.3.0.1)

To add a route over gif0 use 5678::1 in a routec( ) call. For example:
-> routec "add -inet6 2001:DB8:1:: 2001:DB8:5678::1 -prefixlen 64"

To add a route over gif1 use 2001:DB8:9999::1 in a routec( ) call. For example:
-> routec "add -inet6 2001:DB8:4444 2001:DB8:9999::1 -prefixlen 48"

Thus, the route table would include the following entries:


Routes:
2001:DB8:9999:1::/64 gif0
2001:DB8:4444::/48 gif1

20.5.5 Extra Information in ICMP Error Messages

When working with the namecltinput( ) routines, such as pfctlinput( ), the


sockaddr structure used to report the error message is actually an icmp_info
structure that has been cast as a sockaddr structure. The icmp_info structure,
defined in ip_icmp.h, is sockaddr_in structure that has been extended to include
a new field, errorPktLen. This field reports the length of the bad IP packet. For all
non-ICMP error messages, the value of this field is zero.
If this extra information is not of interest to you, you can ignore it and continue
dealing with the ICMP error message as a sockaddr structure or sockaddr_in
structure. When working with ICMP error messages for tunnelled packets, this
length information can be convenient.

452
20 Working with Device Instances
20.6 Adding a BPF Device

20.6 Adding a BPF Device


The Wind River Network Stack supports the BPF as a method for inspecting
incoming data.

Configuring VxWorks for BPF Support

To add support for this feature, include the BPF Support component in your
VxWorks image. This component is listed under the
Network Components > Network device Components folder in Workbench.
The INCLUDE_BPF component automatically executes usrNetBpfDrvInit( ), a
routine from the configlette, net/coreip/usrNetBpfDrv.c. Included in this routine
is a call to bpfDrv( ), which initializes the BPF driver, a prerequisite to creating BPF
device instances.
This component contains the following configuration parameter:

BPF_BUFSIZE_CFG

Synopsis: Specifies the BPF buffer size. For more information, see Creating a
BPF Device, p.453.
Default: 4096
For more information on the externally callable routines associated with the BPF
driver, see the bpfDrv reference entry.

Creating a BPF Device

20
To create a BPF device:
1. Call bpfDrv( ) to initialize the BPF driver. Ensure that this routine does not
return ERROR. The network stack initialization code should already have
called bpfDrv( ), but calling it again is safe and verifies that the driver
initialized successfully and has not been removed since initialization.
2. Call bpfDevCreate( ) to create a BPF device.
STATUS bpfDevCreate
(
char * pDevName, /* I/O system device name */
int numUnits, /* number of device units */
int bufSize /* block size for the BPF device */
)

453
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The device name should be something like /dev/bpf or /bpf/foo. The number
of units should be set to the maximum number of BPF units for the device – for
example, if you want to use /dev/bpf0 and /dev/bpf1, numUnits should be set
to at least 2. The buffer size should be less than or equal to the MTU, and the
buffer you use to read data from the BPF device should be at least as large as
this bufSize. If you specify a buffer size of zero, the call assumes
BPF_BUFSIZE_CFG as the buffer size.
3. Call open( ) to get a file descriptor for one of these BPF units, for example:
bpffd = open( "/dev/bpf0", 0, 0 );

4. Set any desired options for this unit by using ioctl commands – for instance:
int arg = 1;
int status = ioctl (bpffd, BIOCIMMEDIATE, (int)&arg);

5. Use the BIOCSETF ioctl command to set a filter for the BPF device. This filter
is written according to the bpf_program template. Incoming packets that
match this filter will be passed to the associated BPF device.
6. Use the BIOCSETIF ioctl command to attach the file descriptor associated with
your BPF device unit to a specific network interface.
The BPF_TYPE alias finds the type of link level frame. Use it in statements such as:
BPF_STMT(BPF_LD+BPF_TYPE,0) /* Save lltype in accumulator */

The BPF_HLEN alias determines the header length, independently of the variety of
link layer header in use. Use it in statements such as:
BPF_STMT(BPF_LD+BPF_H+BPF_ABS+BPF_HLEN, 6) /* IP fragment field */

454
21
Integrating a New Network
Interface Driver

21.1 Introduction 455


21.2 Configuring VxWorks for Network Interface Drivers 457
21.3 Overview of the MUX 458
21.4 How ENDs and NPT Drivers Differ 462
21.5 Buffer Alignment 470
21.6 Understanding END Implementation 473
21.7 Understanding NPT Driver Implementation 489
21.8 Porting a BSD Driver to the MUX 504
21.9 Supporting Multiple Network Interface Drivers 507
21.10 Avoiding Memory Leaks 509

21.1 Introduction
This chapter describes how to integrate a new network interface driver with
Wind River Network Stack. For this, you use the MUX, which is an interface that
insulates network services from the particulars of network interface drivers, and
vice versa. Currently, the MUX supports two network driver interface styles, the
Enhanced Network Driver (END) interface and the Network Protocol Toolkit
(NPT) driver interface.

455
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

END Interface

The END is the original MUX network driver interface. ENDs are frame-oriented
drivers that exchange frames with the MUX. The NPT-style drivers are
packet-oriented drivers that exchange packets with the MUX. These packets are
stripped of all datalink layer information. Currently, all network drivers supplied
by Wind River are ENDs, as is the generic driver template defined in
templateEnd.c. There is no generic template for an NPT driver.

NPT Driver Interface

Support for the NPT-style driver is part of a set of MUX extensions designed to
facilitate the implementation of MUX-compatible network services. These
extensions include a registration mechanism for an alternative address resolution
utility and support for back ends that let you extend the sockets API so that
applications can use sockets to access a new network service. Both of these features
are described in 22. Integrating a New Network Service.

Polled Mode

This chapter discusses APIs used by drivers to support polled-mode, and APIs
such as muxPollSend( ), which are used to send and receive packets. However, the
network stack itself does not use polled mode. Currently, polled mode is only used
by the WDB agent COMM_END backend in system mode. During system mode
debugging, the WDB agent calls muxPollSend( ) directly in order to pass packets
to the driver, in polled mode.
While it is possible for an application to use a driver that has implemented the
necessary APIs, and call muxPollSend( )—just as the WDB agent does—the
network stack itself does not support sending IP traffic, for example, in polled
mode. The stack will not detect that a driver is in polled mode and, consequently,
will not call the muxPollSend( ).
Thus, polled mode routines cannot be used as a high-performance polling
mechanism for increasing forwarding network performance. The polled mode
routines are recommended to be used only when implementing a driver that could
be used for system mode debugging over WDB.

456
21 Integrating a New Network Interface Driver
21.2 Configuring VxWorks for Network Interface Drivers

21.2 Configuring VxWorks for Network Interface Drivers


The Wind River Network Stack requires the following configuration components
in order to use the MUX to implement network interface drivers:

END Interface Support

MUX Support
These components are all listed under the
Network Components > Core Network Components folder in Workbench.

END Interface Support

The INCLUDE_END component pulls in endLib, which provides support for ENDs
running under the MUX. For this reason, this component also requires
INCLUDE_MUX.

INCLUDE_END also requires the INCLUDE_NETWORK component.


The endLib library also includes functionality that handles much of the routine
work associated with writing an END. It also contains some functionality
specifically designed for use in drivers running over Ethernet.

MUX Support

The INCLUDE_MUX component pulls in support for the MUX interface and the
muxLib and muxTkLib libraries.
Including this component pulls in support for the MUX interface and the muxLib
and muxTkLib modules. The END drivers depend directly on the functionality
supplied by muxLib. For more information on ENDs and their use of muxLib, see
the muxLib reference entries. 21

The NPT-style drivers are packet-oriented drivers that exchange packets with the
MUX. These packets are stripped of all datalink layer information. Support for the
NPT-style driver is provided by muxTkLib. For more information on NPT-style
drivers and their use of muxTkLib, see the muxTkLib reference entries.
The INCLUDE_MUX component has no component dependencies or configuration
parameters.

457
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

21.3 Overview of the MUX


Under the Wind River Network Stack, network interface drivers pass information
up to the network stack through the mediation of an interface layer known as the
MUX. The MUX is designed to insulate network services from the specifics of
network interface drivers and vice versa.
The MUX provides support for features such as multicasting, Ethernet, and
zero-copy transmission. This interface also decouples the network driver and
network protocol layers. This decoupling lets you add new network drivers (not
necessarily Ethernet based) without the need to alter the network protocol.
Likewise, the decoupling lets you add a new network protocol without the need to
modify the existing MUX-based network interface drivers.
To configure and manage network interface devices, use the ifLib, if6Lib,
ifconfig, or routec functionality. The routec( ) routine is a port of the UNIX-style
utility, route( ). Using these kernel-only utilities, you can configure a network
interface for use with IPv4 or IPv6.

21.3.1 The MUX and the OSI Network Model

The OSI Network Model describes seven layers through which data passes when
it is transmitted from an application on one machine to a peer on a remote but
network-connected machine. In practice, not all seven layers are implemented.
Starting in the application layer, data passes down through each layer of the stack
to the physical layer, which handles the physical transmission to the remote
machine. After arriving on the remote machine, data passes up through each layer
from the physical to the application.
In the abstract, each layer in the stack is independent of the other layers. A protocol
in one layer exchanges messages with peers in the same layer on remote machines
by passing the message to the layer immediately below it. Whether the message
passes down through other layers is not its concern. Ideally, the protocol is
insulated from such details.
In practice, network stacks that implement each layer with perfect independence
are rare. Within TCP/IP, the protocols that manage the Transport and Network
layer routines are sufficiently coupled that they are sometimes referred to as the
protocol layer. The MUX is an interface between the datalink and this protocol
layer. The MUX is not a new layer. There are no MUX-level protocols that
communicate with peers in the MUX of a remote machine. The MUX concerns
itself solely with standardizing communication between the protocol and datalink

458
21 Integrating a New Network Interface Driver
21.3 Overview of the MUX

layers of a single stack. Because of the MUX, no protocol or network driver needs
direct knowledge of the other’s internals.

Figure 21-1 The OSI Network Model and the MUX

The network applications that use


Application the data being transferred, for
example HTTP or FTP.

The layer in which data is encrypted,


Presentation translated, or compressed before it
is transmitted.

The layer responsible for establishing


Session and maintaining the connection
between communicating machines.

The layer in which data is packaged


and tracked to assure that the packets
Transport have been received correctly. TCP, the
Transmission Control Protocol, is a
Protocol transport layer protocol.
Layer
The layer that adds routing information
Network to each data packet. IP, the Internet
Protocol, is an example network protocol.
MUX
Interface The layer that prepares the packets
for transmission through the physical
Data Link layer and handles problems such as
packet collision. Ethernet is a data
link protocol.

Physical The actual wiring and hardware that


support the network connection.
21
For example, when a network driver needs to pass up a received packet, the driver
does not directly access any structure or routine within the destination network
service. Instead, when the driver is ready to pass data to the service, the driver calls
a MUX routine that handles the details. The MUX does this by calling the receive
routine that the network service registered with the MUX. This design lets any
MUX-compatible network service use any MUX-compatible network driver.

459
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

21.3.2 The Protocol-to-MUX Interface

To attach to a previously loaded END or NPT device, a protocol calls muxBind( )


or muxTkBind( ). You can use muxBind( ) only with END devices. You can use
muxTkBind( ) to bind a protocol to either an NPT or an END device. Independent
of whether you use muxTkBind( ) or muxBind( ), the network service supplies
pointers to routines that the MUX uses to:
■ shut down the service
■ pass an error message to the service
■ pass a packet to the service
■ restart transmission by the service
The prototypes of these callback routines differ a bit depending on whether you
used muxTkBind( ) or muxBind( ). Using muxTkBind( ) to bind to an END device
imposes an additional layer of translation. A protocol might prefer to provide
muxBind( )-style callbacks and use muxBind( ) to bind to END devices and avoid
the performance impact of the additional translation work.
It can occasionally be useful to call a device-specific MUX routine such as
muxTkSend( ) or muxIoctl( ) without binding to the device. To do this, it is
necessary to obtain the appropriate “cookie” describing a fake binding to the END
or NPT device. Call the muxTkCookieGet( ) routine to obtain such a cookie for the
specified device name and unit number. The muxTkCookieGet( ) routine
allocates no memory, and the returned value does not describe a real binding, so
do not call muxUnbind( ) with this cookie. Also note that the cookie is valid only
while the END or NPT device remains loaded in the MUX.
After the service has bound itself to a driver through the MUX, it can then call
MUX-supplied routines, such as muxSend( ) or muxTkSend( ), to transmit a
packet or request other MUX services.
When working with the Wind River Network Stack, you do not need to make a
direct call to muxTkBind( ). This is handled for you by the internals of ipAttach( )
or ip6Attach( ). For the boot device, the built-in TCP/IP stack initialization code
automatically calls ipAttach( ) and/or ip6Attach( ). To bind the stack to additional
interfaces, you must make explicit attach calls for each additional interface. Again,
the internals of the attach calls handle the muxTkBind( ) call.
To free a network service from a binding to a driver in the MUX, you can call
muxUnbind( ). However, if the binding was created using ipAttach( ) or
ip6Attach( ), you should call ipDetach( ) or ip6Detach( ). These detach calls
handle the muxUnbind( ) and other details.

460
21 Integrating a New Network Interface Driver
21.3 Overview of the MUX

21.3.3 The Data-Link-to-MUX Interface

To add an END or NPT device to the MUX, call muxDevLoad( ) for each driver
you want to add. This is done for you automatically in the standard network
initialization code if you name the driver’s load routine in the endDevTbl[ ]. The
stack initialization code uses this function pointer as input to a muxDevLoad( )
call.
The value returned by muxDevLoad( ) identifies the END or NPT device. You can
use this identifier in a subsequent call to muxDevStart( ), muxDevStop( ), or
muxDevUnload( ). In some previous versions of the stack, this value could also be
passed as an argument to muxIoctl( ) or muxTkSend( ) or muxSend( ). That no
longer works. These latter routines expect a protocol binding cookie returned from
muxBind( ) or muxTkBind( ). A pseudo-bind cookie returned by
muxTkCookieGet( ) also works. See the discussion of muxTkCookieGet( ) earlier
in this chapter.
Internally, the driver’s load routine must allocate, zero out, and partially populate
an END_OBJ structure and a NET_FUNCS structure. The END_OBJ structure
provides the MUX with a description of the device, and the NET_FUNCS structure
provides the MUX with pointers to the driver’s standard MUX interface routines,
xStart( ), xStop( ), xReceive( ), xIoctl( ), and so on.
The muxDevStart( ) call enables transmission and reception on a loaded END or
NPT device. After a device has been started, it can pass packets up to the MUX by
calling muxReceive( ), if it is an END, or muxTkReceive( ), if it is NPT. The MUX
delivers any of these packets to the appropriate bound protocols. If no bound
protocols match the packet type, the packet is discarded.1

NOTE: The Wind River Network Stack expects to borrow the buffers it receives
and thus avoid data copying. If a device cannot transfer incoming data directly
into clusters, the driver must explicitly copy the data from private memory into a
cluster in sharable memory before passing it in an mBlk up to the MUX. 21

When the MUX receive routine is passed a packet with network service type
matching a protocol bound to the device, it calls the protocol’s receive routine,
registered in the earlier call to muxBind( ) or muxTkBind( ). If the protocol receive

1. The mux[Tk]Receive( ) calls in the shipped ENDs and the template END are hard to iden-
tify as such when casually reading the code. When passing a packet up to the MUX, each of
these drivers uses the function pointer referenced in the receiveRtn field of its END_OBJ.
An earlier call to muxDevLoad( ) set the receiveRtn field to muxReceive( ) or
muxTkReceive( ), whichever was appropriate.

461
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

routine returns TRUE (or any non-zero value), the protocol has consumed the
packet. Otherwise, the MUX checks if any other bound protocol can accept the
packet, and if not, discards it, freeing the associated M_BLK tuples. When a
protocol consumes a packet, it is responsible for freeing the packet.
To disable transmission and reception on a device, call muxDevStop( ). Call
muxDevUnload( ) to remove the network interface from the MUX. Note that
muxDevUnload( ) forcibly shuts down any bound protocols; the protocol
shutdown routine should call muxUnbind( ) to unbind the protocol from the
device.

21.4 How ENDs and NPT Drivers Differ


The NPT driver is a packet-oriented equivalent to the frame-oriented END. Both
the NPT driver and the END are organized around the END_OBJ and the
NET_FUNC structures, and both driver styles require many of the same entry
points:

xLoad( ) – load a device into the MUX and associate a driver with the device

xUnload( ) – release a device, or a port on a device, from the MUX

xSend( ) – accept data from the MUX and send it on towards the physical layer

xMCastAddrDel( ) – delete a multicast address registered for a device

xMCastAddrGet( ) – get a list of multicast addresses registered for a device

xMCastAddrAdd( ) – add a multicast address to those registered for a device

xPollSend( ) – send packets in polled mode rather than interrupt-driven mode

xPollReceive( ) – receive frames in polled rather than interrupt-driven mode

xStart( ) – connect device interrupts and activate the interface

xStop( ) – stop or deactivate a network device or interface

xIoctl( ) – support various ioctl commands2

xBind( ) – exchange data with the protocol layer at bind time (optional)3

2. Although the API for both the END and the NPT xIoctl( ) are identical, the NPT xIoctl( )
must support two extra ioctl commands, EIOCGNPT and EIOCGMIB2233.
3. The xBind( ) entry point is not in the NET_FUNCS structure, but it can be returned if the
driver supports the EIOCQUERY ioctl for the END_BIND_QUERY query type.

462
21 Integrating a New Network Interface Driver
21.4 How ENDs and NPT Drivers Differ

In addition to the END_OBJ pointer for the device and the M_BLK pointer for the
packet to be transmitted, an NPT driver send routine takes three more arguments:

a pointer to a character buffer containing the destination MAC address

the network service type value (also known as the ethertype value)

an additional void* pointer.
This is provided for protocols that need to pass additional information to the
driver send routine; the protocol and the driver must both share the same
interpretation of this parameter, if it is used. Normally it is NULL.
The NPT send routine must use the provided destination MAC address and
network service type, and its own known source MAC address, to prepend an
appropriate MAC header to the frame. If the destination MAC address pointer is
NULL, the NPT driver should consider this to indicate that a complete MAC
header has already been prepended to the frame.
In addition to the END_OBJ pointer for the device passed and the M_BLK pointer
for the received packet passed to muxReceive( ), the muxTkReceive( ) routine
called (indirectly) by NPT drivers takes four additional arguments:
■ The offset from the start of the frame to the network-layer header. This is called
the network service offset and is the same as the link header size.
■ The network service type value (ethertype value).
■ A boolean value, which (if TRUE) indicates that the packet is a unicast or
multicast packet that would not have been received were the device not in
promiscuous mode. When this value is TRUE, the received frame is only
passed to SNARF or PROMISCUOUS protocols.
■ An extra void* pointer for additional information which should be passed to
the receiving protocol(s). The protocol and the driver must agree on the
interpretation of this value. Most protocols will ignore this value.
21
The NPT driver parses the link header and passes enough information to the MUX
(and to protocol receive routines) to let them easily strip the link header from the
frame. The NPT driver itself does not remove the link header.
The three END entry points not included in an NPT driver are:4

xAddressForm( ) – add addressing information to a packet

xAddrGet( ) – extract the addressing information from a packet

xPacketDataGet( ) – separate the addressing information and data in a packet
The above routines are optional for NPT drivers because these drivers construct
their own link headers on transmit and parse their link headers on receive.

463
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The following registration interface lets you manage an address resolution routine
for a protocol/interface pair.

muxAddrResFuncAdd( ) – add an address resolution routine

muxAddrResFuncGet( ) – get the resolution routine for ifType/protocol

muxAddrResFuncDel( ) – delete an address resolution routine
For Ethernet devices, the Wind River Network Stack automatically assigns
arpresolve( ) as the address resolution routine. If you are writing an END that does
not run over Ethernet, you also need to implement the xAddressForm( ),
xAddrGet( ), and xPacketDataGet( ) entry points explicitly. ENDs running over
Ethernet typically use the endLib implementations of these routines.

21.4.1 Managing Memory for Network Drivers and Services

The Wind River Network Stack uses netBufLib to manage its internal system and
data memory pools. Similarly, almost all the shipped ENDs use netBufLib to
manage memory pools for their receive buffers. For best performance, drivers are
encouraged to use the linkBufPool back end plug-in to netBufLib, which
provides pools of pre-constructed M_BLK tuples of a single size, ideal for network
driver receive pools.

NOTE: The Wind River Network Stack expects to borrow the buffers it receives
and thus avoid data copying. If a device cannot transfer incoming data directly
into clusters, the driver must explicitly copy the data from private memory into a
cluster in sharable memory before passing it in an mBlk up to the MUX.

21.4.2 Supporting Scatter-Gather in Your Driver

Some devices support breaking up a single network packet into separate chunks
of memory. This makes it possible to handle the outgoing network packets as a
chain of mBlk/clBlk/cluster constructs without any copying.
When a driver gets a chain of mBlks, it can decide how to transmit the clusters in
the chain. If it is able to do a gather-write, it does not need to do any data copying.
If it cannot, then it must collect all of the data from the chain into a single memory
area before transmitting it.

4. For Ethernet, these routines are implemented in endLib. Thus, if your driver runs over
Ethernet (using either 802.3 or DIX header formats), you can reference the existing routines
and do not need to implement them.

464
21 Integrating a New Network Interface Driver
21.4 How ENDs and NPT Drivers Differ

21.4.3 Early Link-Level Header Allocation in an NPT Driver

The NPT driver and its MUX support routines are automatically configured to
allocate extra room at the beginning of an outgoing packet to hold the network-
and transport-layer header information. This allows those layers to copy in their
headers without additional overhead in the form of memory allocation and buffer
chaining.

NOTE: The MUX and the NPT driver have nothing to do with the amount of space
reserved at the start of a packet for network, transport, or link header information.
It is the protocols that provide the buffers and the packets to be transmitted that
control this.

You can configure the NPT-supporting MUX routines to also allocate extra room
for the data-link-layer header by setting the MAX_LINKHDR_CFG configuration
parameter or #define in the configNet.h file for your BSP. You should set this
value to the largest of the data-link-layer header sizes used by the drivers in your
system. For instance, if you add the following line:
#define MAX_LINKHDR_CFG 16

sixteen extra bytes will be prepended to outgoing packets, and drivers with
data-link-layer headers of 16 bytes or fewer will have that space available in the
packet without having to prepend a new mBlk during their endAddressForm( ) or
nptSend( ) routines.

NOTE: MAX_LINKHDR_CFG controls the Wind River TCP/IP protocols, not the
MUX. Setting MAX_LINKHDR_CFG large enough for an NPT's MAC header
makes it more likely that the driver send routine will not have to allocate an
additional tuple to store the MAC header, but does not guarantee this.

When using the M_PREPEND( ) macro to add a header to a packet, this extra space
will be automatically used (or, if the space has not been pre-allocated, a new mBlk 21
will automatically be generated and prepended). See 3.4.4 Using Macros for Buffer
Manipulation, p.47.

21.4.4 MIB Statistics Collection in END and NPT Drivers

The interface by which END and NPT drivers collect and report packet statistics to
the stack has changed. No longer does a driver need to use different code to
support RFC 2233 and RFC 1213. A unified interface lets network drivers pass
packet statistics to the stack on a per-packet basis. Alternatively, a driver can

465
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

collect supported statistics which will be polled (at fairly low frequency) by the
stack. This may give better performance, especially if the device hardware
maintains some of the needed statistics. The polled statistics mode requires that
the component INCLUDE_MIB2_IF be configured into the VxWorks image.

Configuring VxWorks for Counter Instrumentation

The Wind River Network Stack supports counter instrumentation. To add support
for this feature, include the Auto IPv4 Address Configuration component in your
VxWorks image. This component is listed under the
Network Components > Network Protocol Components >
Network Components for MIB2 folder in Workbench.
The INCLUDE_MIB2_IF component pulls in the software modules and MIB files
that SNMP needs to provide access to the network interface layer. Included in
these modules is m2IfLib, which describes the externally callable function
associated with INCLUDE_MIB2_IF. This library provides MIB-II services for the
interface group. It provides routines to initialize the group, access the group scalar
variables, read the table interfaces, and change the state of the interfaces.
There are no component dependencies for INCLUDE_MIB2_IF.
This component includes three configuration parameters. The first two let you
specify the parameter values that the stack initialization code uses when it calls
m2IfInit( ).

MIB2IF_TRAP_RTN

Synopsis: Pointer to a user-supplied SNMP trap generator.


Default: NULL

MIB2IF_TRAP_ARG

Synopsis: Argument to the user-supplied SNMP trap generator function.


Default: NULL

MIB2IF_LONG_COUNTERS

Synopsis: Enable or disable 64-bit counters from RFC 2233.


Default: FALSE

For more information on these parameters, see the reference entry for m2IfInit( ).

466
21 Integrating a New Network Interface Driver
21.4 How ENDs and NPT Drivers Differ

Calling the Driver Routines

A driver’s load routine should call endM2Init( ) to provide needed interface


information to the stack. The information includes the interface type, the MAC
address and its length, the MTU, the interface's data rate (that is, wire speed), and
interface flags.
The endM2Init( ) routine will initialize the MIB interface data structures and store
this information as appropriate to either RFC 1213 or RFC 2233, whichever is
configured into the VxWorks image. For example:
endM2Init(&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
(u_char *) &pDrvCtrl->enetAddr, 6, ETHERMTU,
MOT_TSEC_PHY_SPEED_1000,
IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST |
IFF_SIMPLEX);

The driver's unload routine calls endM2Free( ) to release any MIB-related data
structures for which memory was allocated by endM2Init( ).
endM2Free (&pDrvCtrl->endObj);

If a driver wishes to support the polled statistics mode, it adds two members to its
device control structure:
END_IFDRVCONF endStatsConf;
END_IFCOUNTERS endStatsCounters;

The driver load routine should initialize these members after calling endM2Init( ):
bzero ((char *)&pDrvCtrl->endStatsCounters, sizeof(END_IFCOUNTERS));

pDrvCtrl->endStatsConf.ifPollInterval = sysClkRateGet();
pDrvCtrl->endStatsConf.ifEndObj = &pDrvCtrl->endObj;
pDrvCtrl->endStatsConf.ifValidCounters = (END_IFINUCASTPKTS_VALID |
END_IFINMULTICASTPKTS_VALID |
END_IFINBROADCASTPKTS_VALID |
END_IFINOCTETS_VALID |
END_IFOUTOCTETS_VALID |
END_IFOUTUCASTPKTS_VALID | 21
END_IFOUTMULTICASTPKTS_VALID |
END_IFOUTBROADCASTPKTS_VALID);

The ifValidCounters member is a set of bit flags indicating which statistics the
driver supports, i.e. which of the END_IFCOUNTERS members the driver will fill
in. The ifPollInterval member sets the period (in system clock ticks) at which the
stack polls statistics.
The ifEndObj merely points to the END_OBJ structure for the interface.
The remaining members of the END_IFDRVCONF structure are initialized by code
outside the driver.

467
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The driver's endIoctl( ) routine should implement a few MIB-related commands.


The following code comes from the motTsecEnd.c driver (and some additional
comments have been added):
/*
* All drivers should support EIOCGMIB2233 and EIOCGMIB2
* by calling endM2Ioctl().
*/
case EIOCGMIB2233:
case EIOCGMIB2:
/* These commands retrieve the interface statistical
* data structures used for RFC 2233 or RFC 1213, respectively.
* Note that the driver doesn't access these directly.
*/
error = endM2Ioctl (&pDrvCtrl->endObj, cmd, data);

break;

/*
* The EIOCGPOLLCONF and EIOCGPOLLSTATS commands are implemented
* only if the driver wishes to support polled statistics retrieval.
* EIOCGPOLLCONF retrieves a pointer to the polling configuration
* structure (as initialized by the driver load routine).
* EIOCGPOLLSTATS first collects the statistics into the
* END_IFCOUNTERS structure, retrieving them from the hardware if
* necessary, and the stores a pointer to that structure at the
* indicated address.
*/

case EIOCGPOLLCONF:
if ((data == NULL))
error = EINVAL;
else
*((END_IFDRVCONF **)data) = &pDrvCtrl->endStatsConf;
break;

case EIOCGPOLLSTATS:
if ((data == NULL))
error = EINVAL;
else
{
/* retrieve the statistics from the hardware */
error = motTsecEndStatsDump(pDrvCtrl);
if (error == OK)
*((END_IFCOUNTERS **)data) = &pDrvCtrl->endStatsCounters;
}
break;

Drivers loaded by the startup code that support polling will have polling started
automatically. For drivers loaded later, manually or by application code, the
endPollStatsInit( ) routine may be called to start polling:
endPollStatsInit (pCookie, m2PollStatsIfPoll);

Here pCookie is the device cookie returned by muxDevLoad( ).

468
21 Integrating a New Network Interface Driver
21.4 How ENDs and NPT Drivers Differ

Either way, polling takes place in the context of tNetTask, by calling the driver's
endIoctl routine with the EIOCGPOLLSTATS command. The handler for that
command should retrieve from the hardware the supported statistics and store
them in the appropriate members of the driver’s END_IFCOUNTERS structure
(endStatsCounters in the example above). The counts stored should be the counts
accumulated since the last polling call, or (on the first call only) those accumulated
since the interface was started.

NOTE: Poll mode should only be used for debugging. For details, see Polled Mode,
p.456.

A driver which does not support the polled mode statistics collection should not
implement the EIOCGPOLLCONF and EIOCGPOLLSTATS end ioctl commands.
Instead, it accumulates statistics per packet by calling the endM2Packet( ) routine,
as follows.
For successfully transmitted packets, the driver calls:
endM2Packet(&pDrvCtrl->endObj, pMblk, M2_PACKET_OUT);

For packets which could not be transmitted due to a resource limitation (not for
normal TX stalls), the driver should call:
endM2Packet (&pDrvCtrl->endObj, NULL, M2_PACKET_OUT_DISCARD);

For packets which the driver detected a transmission error (not a resource
limitation or a normal TX stall), the driver calls:
endM2Packet(&pDrvCtrl->endObj, NULL, M2_PACKET_OUT_ERROR);

For successfully received packets, the driver calls:


endM2Packet(&pDrvCtrl->endObj, pMblk, M2_PACKET_IN);

For packets received with errors, the driver calls:


endM2Packet (&pDrvCtrl->endObj, NULL, M2_PACKET_IN_ERROR);
21
(and does not ordinarily deliver the packets to the stack). For packets which could
not be received due to resource limits, the driver should call:
endM2Packet (&pDrvCtrl->endObj, NULL, M2_PACKET_IN_DISCARD);

Note that collection of such failure statistics could be a best-effort activity.

469
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

21.5 Buffer Alignment


Some microprocessors, most notably those from MIPS and ARM, restrict data
access for long words (32-bit values) to the four-byte boundary. Accessing a 4-byte
quantity at an address which is not 4-byte aligned may result in an alignment
exception or other unpleasant results. For any structure containing a 4-byte
member which the compiler expects to be 4-byte aligned, the compiler takes care
of the alignment within the structure; but the compiler must assume that the
structure starts on an aligned 4-byte boundary.5
Many protocols (IP, TCP, and the like) specify four-byte fields in their headers.
Conveniently, these protocol packets are usually set up so that these four-byte
fields align on four-byte boundaries relative to the start of the protocol packet.
Thus, if your network driver passes up a buffer in which the payload data (for
example, an IP packet) always starts at an absolute four-byte boundary, the fields
within the data should align correctly.

! WARNING: When working with alignment-sensitive hardware, if the payload data


contains fields that the stack accesses as long words, those fields must align on
absolute four-byte boundaries. Otherwise, the stack crashes when it tries to access
those long word fields.

Unfortunately, when a packet first arrives, its datalink layer header might not end
on an absolute four-byte boundary. For example, the RFC 894 Ethernet packet (see
Figure 21-2) has a 14-byte header that precedes the payload data.

Figure 21-2 RFC 894 Ethernet Packets Are Problematic for Alignment-Sensitive Hardware

Buffer Containing an RFC 894 Packet

RFC 894 Ethernet Header: Data payload, consisting internally of four-byte


Six-byte Destination Address, aligned objects that are misaligned relative to
Six-byte Source Address, the absolute four-byte boundaries because of
Two-byte Type Field, total of 14 bytes the 14-byte RFC 894 header.

5. If the buffer contains a four-byte region that you access as an array of 8-bit or 16-bit values,
there is no alignment restriction. The restriction applies only when you access long words.

470
21 Integrating a New Network Interface Driver
21.5 Buffer Alignment

If you receive this type of Ethernet packet on a long word boundary, any four-byte
aligned payload data (such as an IP packet) following such a header would be
misaligned because the payload data would start on a two-byte boundary. If you
pass this misaligned data up to the MUX, the stack crashes.
To guarantee correctly aligned payload data, your driver can:

copy the data (the worst-case solution)
■ offset the receive buffers (often impossible on hardware that needs it)
■ use a scatter-gather receive (the most elegant solution)

Copying the Data

The simplest solution to the alignment problem is for the driver to copy each
packet upon reception such that the data aligns properly. The driver can then
safely pass the data up to the MUX. Because such a copy is time consuming, it is a
worst-case solution.
Often, it is sufficient to copy just enough of the start of the packet to contain all
protocol headers into a separate tuple's cluster, with the network header at least
4-byte aligned. Protocol payload data (for example, TCP or UDP payload) is
typically copied into user application buffers, and this copy itself has no alignment
restrictions. Applications might need to be careful to align the data buffers they
receive this payload into, of course. Buffers allocated using malloc( ) will have
sufficient alignment.

Offsetting the Receive Buffers

On some hardware, the driver can offset the receive buffers that it gives to the
hardware such that the protocol headers within the received packets start at a
four-byte boundary. This mis-aligns the MAC header, but this is not usually a 21
problem. Neither the stack nor the MUX ever access Ethernet header data as
anything but 8-bit and 16-bit quantities. Thus, the access restriction that applies to
long words only does not apply.
To succeed, this approach relies on the ability to DMA data into a misaligned (non
four-byte aligned) buffer. Unfortunately, some DMA controllers do not allow
misaligned buffers. In fact, on boards that have CPUs with alignment issues, these
issues are usually pushed down into the rest of the hardware infrastructure,
including the DMA engines. Thus, this approach is often impossible on the very
hardware that requires it.

471
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Figure 21-3 Receiving an RFC 894 Packet into an Offset Buffer

Offset Buffer Containing an RFC 894 Packet

Two-byte RFC 894 Data payload, consisting internally of four-byte objects


Offset Ethernet Header now correctly aligned relative to the absolute four-byte
boundaries because of the two-byte offset.

In Figure 21-3, the Ethernet header no longer starts on a four-byte boundary.


Therefore, neither the destination address nor the type fields in the Ethernet
header fall on four-byte boundaries. Because the stack does not access either of
these fields as long words, no segmentation fault occurs.

Using a Scatter-Gather Receive

If the hardware can handle scatter-gather lists, your driver can use this feature to
handle the alignment problem elegantly. For each packet, your driver allocates
two buffers: one buffer for the MAC layer header data (Ethernet header), and a
second buffer for the payload data (such as an IP datagram). See Figure 21-4.

Figure 21-4 Receiving an RFC 894 Packet into Two Linked Scatter-Gather Buffers

First Buffer Second Buffer

RFC 894 2 Bytes Payload data, the internally four-byte aligned data is also
Header Empty correctly aligned relative to the absolute four-byte boundaries.

On reception, the device places the MAC header into one buffer and the payload
data into the other. The driver receive routine then links these together and
processes them as a buffer chain in which each component buffer automatically
starts on a four-byte boundary. Therefore, when the driver hands the buffer chain
up to the MUX, the payload data is correctly aligned. This solution assumes that
the length of the scatter-DMA buffers is arbitrary, and need not be (for instance) a
multiple of 4.

472
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

21.6 Understanding END Implementation


This section presents an overview of how an END operates followed by
implementation recommendations for the standard END entry points. If you
compare this section with 21.7 Understanding NPT Driver Implementation, p.489,
you will notice a strong parallelism. This is because the NPT is a generalized
extension of the END. Thus, the implementation recommendations for both driver
styles are nearly identical. The few differences that do exist are critical.
If you are writing an END, you are writing a driver that runs over Ethernet and
that passes its packets up to the Wind River Network Stack. As a starting point for
your END, you should use the generic END in:
installDir/vxworks-6.n/target/src/drv/end/templateEnd.c

21.6.1 END Operation

This subsection presents an overview of the following END operations:



adding an END to the Wind River Network Stack

launching an END

responding to a service bind event

receiving frames

NOTE: For instructions on starting additional drivers at run-time, see 20.2 Working
with Network Driver Instances, p.432.

For the most part, the NPT and the END handle these operations identically. The
major exception is in the area of receiving frames. NPT drivers pass up information
that makes it easy to strip the datalink header, but the header is still present when
the NPT driver passes a received frame to the MUX.
21

Adding an END

Adding your driver to the Wind River Network Stack is much like adding any
other application to a target image. The first step is to compile and include the
driver code in the image.
Because the Wind River Network Stack allows you to create more than one
network device, you must set up a table that groups the #define statements that
configure these devices into device-specific groups.

473
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This table, endDevTbl[ ],is defined in the configNet.h file in your directory:
installDir/vxworks-6.n/target/config/bspname
Where bspname is the name of your board support package, such as mv162 or
pc486. For example, to add an ln7990 END, you would edit configNet.h to contain
lines such as:
/* Parameters for loading ln7990 END supporting buffer loaning. */
#define LOAD_FUNC_0 ln7990EndLoad
#define LOAD_STRING_0 "0xfffffe0:0xffffffe2:0:1:1"
#define BSP_0 NULL

You should define three constants, like those shown above, for each of the devices
you want to add. To set appropriate values for these constants, consider the
following:
LOAD_FUNC
Specifies the name of your driver’s endLoad( ) entry point. For example, if your
driver’s endLoad( ) entry point were ln7990EndLoad( ), you would edit
configNet.h to include the line:6
#define LOAD_FUNC_n ln7990EndLoad
LOAD_STRING
Specifies the initialization string passed into muxDevLoad( ) during network
initialization as the initString parameter. This string is passed along blindly to
the endLoad( ) routine of the driver, and its contents depend on what the
driver expects.
Some BSPs define LOAD_FUNC as a wrapper routine which is responsible for
calling the real driver load routine with appropriate arguments. In this case,
LOAD_STRING is often NULL.
You must also edit the definition of the endDevTbl[ ] (a table in configNet.h that
specifies the ENDs included in the image) to include entries for each of the devices
to be loaded:
END_TBL_ENTRY endDevTbl [] =
{
{ 0, LOAD_FUNC_0, LOAD_STRING_0, BSP_0, NULL, FALSE },
{ 1, LOAD_FUNC_1, LOAD_STRING_1, BSP_1, NULL, FALSE },
{ 0, END_TBL_END, NULL, 0, NULL, FALSE },
};

6. Do not confuse END entry points, indicated as endLoad( ), endStart( ), and so on, with
routines in endLib, an END support library that defines routines such as
endTxSemTake( ) and endTxSemGive( ).

474
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

The first number in each table entry specifies the unit number for the device. The
first entry in the example above specifies a unit number of 0. Thus, the device it
loads is deviceName0. The FALSE at the end of each entry indicates that the entry
has not been processed. After the system has successfully loaded a driver, it
changes this value to TRUE in the run-time version of this table. To prevent the
system from automatically loading your driver, set this value to TRUE.
Some BSPs create entries in the endDevTbl[] at run-time. This could make it easier
to deal with dynamically discovered network hardware, and it can make device
configuration more flexible. When endDevTbl[] is generated at run-time, it is
typically pre-filled with a number of empty entries that can be consumed as
network devices are discovered.
At this point, you are ready to rebuild the Wind River Network Stack to include
your new drivers. When you boot this rebuilt image, the system calls
muxDevLoad( ) for each device specified in the table in the order listed.

NOTE: The endDevTbl[ ] can contain a mix of NPT drivers and ENDs.

Launching the Driver

At system startup, the Wind River Network Stack spawns the user root task,
which initializes the network. This task calls muxDevLoad( ), which calls the
endLoad( ) routine in your driver. This endLoad( ) routine creates and partially
populates an END_OBJ structure that describes the driver. Among the information
that endLoad( ) must supply in the END_OBJ is a reference to a NET_FUNCS
structure that endLoad( ) has allocated and populated with references to the driver
entry points. Typically, the END_FUNCS structure is static and is shared between
all network devices managed by the driver.
After muxDevLoad( ) loads your driver, a muxDevStart( ) call executes the
21
endStart( ) routine in your driver. The endStart( ) routine should activate the driver
and register an interrupt service routine for the driver with the appropriate
interrupt connect routine for your architecture and BSP.

Binding to a Service

An END typically does not react when a service binds to a device. An END may
take advantage of the same facility used by an NPT driver to exchange data with a
service during the bind phase. See Responding to Network Service Bind Calls, p.491,
for more complete information on this process.

475
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Receiving Frames

When a device receive interrupt occurs, the Wind River Network Stack invokes
the interrupt service routine that was registered by the endStart( ) routine. This
interrupt service routine should do the minimum amount of work necessary to
transfer the frame from the local hardware into accessible memory (ideally a
cluster: see 21.3.3 The Data-Link-to-MUX Interface, p.461).
To minimize interrupt lockout time, your ISR should handle directly (at interrupt
level) only those actions that require minimum execution time, such as error
checking or device status change. The ISR should queue all time-consuming work
for processing at task level.
The ISR should disable further receive interrupts and set a flag indicating that it
has posted work to task level. If this flag is already set when the ISR is entered,
another job (for the same type of event, that is, frame reception) need not be posted.
This could occur when more than one device shares the same interrupt line.
To queue frame reception work for processing at the task level, your ISR can use
netJobAdd( ). This routine takes a function pointer and up to five additional
arguments (representing parameters to the routine referenced by the function
pointer).
The netJobAdd( ) routine prototype is:
STATUS netJobAdd
(
FUNCPTR routine,
int param1,
int param2,
int param3,
int param4,
int param5
)

The routine in this case should be the routine in your driver that performs frame
processing at the task level. The netJobAdd( ) routine puts that routine on
tNetTask’s work queue and gives a semaphore that awakens tNetTask.
Upon awakening, tNetTask dequeues routine calls and associated arguments
from its work queue. It then executes these routines in its context until the queue
is empty.
Your task-level frame reception routine should do whatever is necessary to
construct an mBlk chain containing the frame to hand off to the MUX, such as
assuring data coherency. When all is ready, your driver passes the frame up to the
MUX by calling the routine referenced in the receiveRtn field of the END_OBJ
structure that represents your device (see B.3.3 END_OBJ, p.594).

476
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

The receive routine should continue processing received frames until either there
are no more to be processed, or a (modest) limit number of frames has been
processed. If there are no more frames to process, the receive routine should clear
the flag set by the ISR indicating that receive work has been posted, then re-enable
receive interrupts, and return. If the frame limit is reached, the receive routine may
repost itself using another netJobAdd( ) call, and return. It should not re-enable
receive interrupts in this case. Reposting another net job rather than simply
continuing to process within the same net job, allows other enqueued net jobs to
run, which is necessary for good performance.
Transmission complete interrupts should be handled similarly: disable further
transmit complete interrupts, and post a net job to do transmit resource clean-up
work, such as freeing M_BLK chains, at task level. The transmit clean-up routine
cleans up as many packets as are ready. If the device was previously stalled and
there are now sufficient free transmit DMA descriptors, muxTxRestart( ) is posted
as a net job to restart transmission, and the stall flag is cleared. The transmit
clean-up routine then re-enables transmit complete interrupts and returns. Some
drivers may choose to use a combined routine for both transmit cleanup and
receive work.

21.6.2 The END Interface to the MUX

This subsection describes the driver entry points and the shared data structures
that comprise an END’s interface to the MUX.

Data Structures Shared by the END and the MUX

The core data structure for an END is the END object, or END_OBJ. This structure
is defined in target/h/end.h (see also B.3.3 END_OBJ, p.594). The driver’s load
routine returns a pointer to an END_OBJ that it allocated, zeroed out, and partially 21
populated. This structure supplies the MUX with information that describes the
driver as well as a pointer to a NET_FUNCS structure populated with references to
the END’s standard entry points.
Although the driver’s load routine is responsible for populating much of the
END_OBJ structure, some of its members are set within the MUX when a protocol
binds to the device. Specifically, the MUX maintains the array of protocols bound
to the END_OBJ. When the driver calls its registered receive routine (a
muxReceive( ) or a muxTkReceive( ) call), this routine calls the bound protocol
receive routines appropriate for the received packet.

477
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

END Entry Points Exported to the MUX

Table 21-1 lists the standard driver entry points that the NET_FUNCS structure
exports to the MUX. In this manual, the routines use a generic “end” prefix, but in
practice this prefix is usually replaced with a driver-specific identifier, such as
"ln7990" for the Lance Ethernet driver.

Table 21-1 END Routines

Routine Description

endLoad( ) Load a device into the MUX and associate a driver with the
device.

endUnload( ) Release a device, or a port on a device, from the MUX.

endSend( ) Accept data from the MUX and send it on to the physical
layer.

endMCastAddrDel( ) Remove a multicast address from those registered for the


device.

endMCastAddrGet( ) Retrieve a list of multicast addresses registered for a


device.

endMCastAddrAdd( ) Add a multicast address to the list of those registered for


the device.

endPollSend( ) Send frames in polled mode rather than interrupt-driven


mode. Poll mode should only be used for debugging.

endPollReceive( ) Receive frames in polled mode rather than


interrupt-driven mode. Poll mode should only be used
for debugging. For details, see Polled Mode, p.456.

endStart( ) Connect device interrupts and activate the interface.

endStop( ) Stop or deactivate a network device or interface.

endAddressForm( ) Add addressing information to a packet.

endAddrGet( ) Extract the addressing information from a packet.

endPacketDataGet( ) Separate the addressing information and data in a packet.

endIoctl( ) Support various ioctl commands.

478
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

endLoad( )

Before a network interface can be used to send and receive frames, the appropriate
device must be loaded into the MUX and configured. The muxDevLoad( ) routine
calls your driver’s endLoad( ).
This routine takes an initialization string, the contents of which are user-defined
but generally include such items as the unit number identifying the physical
interface7, an interrupt vector number, and the address of memory mapped
registers.
The endLoad( ) routine must be written as a two-pass algorithm. The MUX calls it
twice during the load procedure. In the first pass, the initialization string is blank
(all zeros). The endLoad( ) routine is expected to check for the blank string and
return with the name of the device copied into the string. A second call is then
made to endLoad( ) with the actual initialization string that was supplied to
muxDevLoad( ). The endLoad( ) then must return a pointer to the END_OBJ that it
allocates or a NULL if the load fails.
Typically, the endLoad( ) routine, in its second pass, will:
■ Initialize the device and interface.
■ Allocate, zero out, and then populate the END_OBJ structure.
■ Initialize any necessary private structures.
■ Parse and process the initialization string.
■ Call endM2Init( ) to initialize MIB interface statistics structures.
■ Create and initialize a private pool of memory using the API in netBufLib.
The endLoad( ) routine is based on the following skeleton:
END_OBJ * endLoad
(
char * initString, /* defined in endTbl */
void * pBsp /* BSP-specific information (optional) */
)
{ 21
END_OBJ * newEndObj;

if( !initString ) /* initString is NULL, error condition */


{
/* set errno perhaps */
return ((END_OBJ *) ERROR);
}

7. Although a driver is only loaded once, the driver’s endLoad( ) routine will be called for
each port to be activated within the driver. This is so the MUX may allocate an entry for each
port. The MUX interface does not impose restrictions on how drivers handle multiple ports
as long as a separate END_OBJ is allocated for each port.

479
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

else if( initString[0] == 0 ) /* initString[0] is NULL, pass one */


{
strcpy( initString, "foo" );
return (END_OBJ *) NULL;
}
else /* initString is not NULL, pass two */
{
/* initialize device */
newEndObj = (END_OBJ *) malloc( sizeof(END_OBJ) );
/* call END_OBJ_INIT() to initialize some MUX-owned fields */
/* call endM2Init() to initialize MIB statistics stuff */
/* initialize any needed private structures */
/* parse and process initString, and pBsp if necessary */
/* create a private pool of memory using netBufLib API */
/* create network buffer pools using netBufLib API */
return( newEndObj );
}
}

endUnload( )

An endUnload( ) routine is invoked when muxDevUnload( ) is called by the


system application. In this routine, the driver is responsible for doing whatever is
necessary to “release” the device.
This generally involves making sure the device is stopped if necessary,
deallocating memory for the device, freeing any net pool tuples held by the driver,
and releasing network pools created with netPoolCreate( ) by calling
netPoolRelease( ). A call to netPoolRelease( ) will arrange for a pool to be freed
after the stack has released all resources from the network pool which it is holding.
For pools created with netPoolInit( ), there is no such safe pool release routine,
and the driver must be sure that all tuples have been returned to the pool before it
returns successfully from endUnload( ). If it cannot do so, it should return an error.
This is one reason why netPoolCreate( ) is preferred over netPoolInit( ) for driver
memory usage.
If the driver has any resources shared among all of its device instances, it must not
free these shared resources until the driver's endLoad( ) routine has been called for
all of the driver's loaded devices.
The endUnload( ) routine does not need to notify services about unloading the
device. Before calling endUnload( ), the MUX sends a shutdown notice to each
service attached to the device.
The endUnload( ) prototype is:
STATUS endUnload
(
END_OBJ * pEND /* END object */
)

480
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

endSend( )

The network driver’s send routine is referenced from the NET_FUNCS table that is
created during the load process. The MUX calls this routine when the network
service issues a send request. The send routine is supplied a reference to an mBlk
chain representing the link-level frame to be sent.
The endSend( ) prototype is:
STATUS endSend
(
END_OBJ * pEND, /* END object */
M_BLK_ID pPkt /* mBlk chain containing the frame */
)

This routine should return a status of:


■ OK, if the send was successful.
■ END_ERR_BLOCK, if the send could not be completed because of a transient
problem such as insufficient resources.
■ This is normal transmit flow control, and is not considered an error. If the send
routine returns END_ERR_BLOCK, the driver's transmit side is said to be
stalled, and the driver must arrange for muxTxRestart( ) to be called when the
driver has sufficient resources to complete the send.
■ The driver may require that a certain high-water-mark of transmit resources
be available before it calls muxTxRestart( ). However, muxTxRestart( ) must
in all cases be called. The driver must not rely upon such a subsequent send call
being made.
■ When the send routine returns END_ERR_BLOCK, the M_BLK chain describing
the packet is still owned by the stack. If the send routine returns any other
value, it takes ownership of the M_BLK chain. The driver must arrange for
reasonably prompt freeing of these M_BLK chains after transmission
completes. 21

ERROR, in this case, errno should be set appropriately.

endMCastAddrAdd( )

This routine registers a physical-layer multicast address with the device. It takes as
arguments a pointer to the END_OBJ returned by endLoad( ) and a string
containing the physical address to be added.
This routine should reconfigure the interface in a hardware-specific way that lets
the driver receive frames from the specified address.

481
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NOTE: To help you manage a list of Ethernet multicast addresses, the Wind River
Network Stack provides the etherMultiLib library.

The endMCastAddrAdd( ) prototype is:


STATUS endMCastAddrAdd
(
END_OBJ * pEND, /* END object */
char * pAddress /* physical address or a reference thereto */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

endMCastAddrDel( )

This routine removes a previously registered multicast address from the list
maintained for a device. It takes as arguments a pointer to the END_OBJ returned
by endLoad( ), and a string containing the physical address to be removed.
The endMCastAddrDel( ) prototype is:
STATUS endMCastAddrDel
(
END_OBJ * pEND, /* END object */
char * pAddress /* physical address, or a reference thereto */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

endMCastAddrGet( )

This routine retrieves a list of all multicast addresses that are currently active on
the device. It takes as arguments a pointer to the END_OBJ returned by endLoad( ),
and a pointer to a MULTI_TABLE structure into which the list will be put.
The endMCastAddrGet( ) prototype is:
STATUS endMCastAddrGet
(
END_OBJ * pEND, /* driver's control structure */
MULTI_TABLE * pMultiTable /* container for address list */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

482
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

endPollSend( )

This routine provides a polled-mode equivalent to the driver’s interrupt-driven


send routine. It must either transfer a frame directly to the underlying device, or it
must exit immediately if the device is busy or if resources are unavailable.

NOTE: Poll mode should only be used for debugging. For details, see Polled Mode,
p.456.

NOTE: When the system calls your endPollSend( ) routine, it is probably in a mode
that cannot service kernel calls. Therefore, this routine must not perform any
kernel operations, such as taking a semaphore or allocating memory. Likewise, this
routine must not block or delay because the entire system might halt.

Your driver's endPollSend( ) is passed a pointer to the device's END_OBJ structure


and a pointer to an M_BLK chain describing the packet to be transmitted. The
routine can return OK, EAGAIN, or ERROR. The errno variable should not be set.
A return of OK indicates that the packet has been successfully sent. EAGAIN
indicates that the driver or device is not ready to transmit a frame, and the caller
should try again in a little while. The endPollSend( ) routine may wait for short
periods of time for the hardware to reach a state where another transmission is
possible, although it is preferable to return EAGAIN and let the caller drive the
polling.
The ERROR return should never actually happen. It indicates an argument error by
the caller or a fatal condition which prevents the provided packet from ever being
sent. [Note that the WDB agent, typically the only user of the polled mode routines,
may treat any non-zero return as equivalent to EAGAIN.]
The endPollSend( ) prototype is:
STATUS endPollSend
(
END_OBJ * pEND, /* END object*/
21
M_BLK_ID pMblk /* mBlk chain: data to be sent */
)

endPollReceive( )

This routine receives frames using polling instead of an interrupt-driven model.


This routine is passed a pointer to the device END_OBJ, and an M_BLK pointer,
pPkt.

NOTE: Poll mode should only be used for debugging. For details, see Polled Mode,
p.456.

483
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

If a frame has been received, this routine retrieves the frame and copies it into the
buffer of length pPkt->mBlkHdr.mLen at address pPkt->mBlkHdr.mData, and
returns OK. When copying the frame to the destination buffer, the driver should
advance pPkt->mBlkHdr.mData by a small offset if necessary to properly align
the network layer header on a 4-byte boundary, and should adjust
pPkt->mBlkHdr.mLen and pPkt->mBlkBlkHdr.len to indicate the actual
pPkt->length of the frame. (The routine should verify that the original buffer is
large enough to hold the frame, taking the offset into account; if not, it should drop
the frame and return EAGAIN. This is merely for safety. It is the caller’s
responsibility to provide buffers large enough to receive the largest frame allowed
by the link type.)
If no frame is currently available, the routine returns EAGAIN, indicating that the
caller should try again later.
Within the endPollReceive( ) routine, verify that the device has been set to
polled-mode (by a previous endIoctl( ) call). The routine should then retrieve the
frame directly from the network and copy it into the mBlk passed in to the routine.
It takes as arguments a pointer to the END_OBJ structure returned by endLoad( )
and a reference to an mBlk or mBlk chain into which the incoming data should be
put.
The endPollReceive( ) prototype is:
STATUS endPollReceive
(
END_OBJ * pEND, /* returned from endLoad() */
M_BLK_ID pPkt /* mBlk chain: data being received */
)

This routine should return OK or an error value of EAGAIN if the received data is
too large to fit in the provided mBlk, or if no data is available.

endStart( )

The driver’s endStart( ) routine connects device interrupts and makes the interface
active and available. This routine takes as its argument the unique interface
identifier returned from the endLoad( ) call. As with endLoad( ), this call is made
for each port that is to be activated within the driver.
The endStart( ) prototype is:
STATUS endStart
(
END_OBJ * pEND, /* END object */
)

484
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

endStop( )

The driver’s endStop( ) routine halts a network device, typically by disconnecting


the appropriate interrupt. It does not remove the device by releasing the allocated
data structures. This routine takes as its argument the unique interface identifier
returned from the endLoad( ) call.
The endStop( ) prototype is:
STATUS endStop
(
END_OBJ * pEND, /* END object */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

endAddressForm( )

The endAddressForm( ) routine generates a frame-specific header and prepends it


to the mBlk chain containing outgoing data. After adding the address segment to
the mBlk, the routine should adjust the mBlk.mBlkHdr.mLen and
mBlk.mBlkHdr.mData members accordingly.
If the incoming mBlk is not large enough to contain the added address
information, an additional mBlk/clBlk cluster must be created for this purpose,
and inserted at the beginning of the mBlk chain. For information on how to
prevent this extra allocation and chaining, see 21.4.3 Early Link-Level Header
Allocation in an NPT Driver, p.465.
The network protocol type can be found in the pDst.mBlkHdr.reserved field.
A reference to the new mBlk chain head is returned from endAddressForm( ).
21
The endAddressForm( ) prototype is:
M_BLK_ID endAddressForm
(
M_BLK_ID pData /* mBlk chain containing outgoing data */
M_BLK_ID pSrc, /* source address, in an mBlk */
M_BLK_ID pDst, /* destination address, in an mBlk */
BOOL bcastFlag /* use link-level broadcast ? */
)

485
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NOTE: The endLib library contains an address formation routine that generates
and prepends Ethernet frame headers. Thus, you probably do not need to
implement this routine if you are running over Ethernet.

endAddrGet( )

This routine retrieves the address values for an incoming frame provided in an
mBlk chain. If the additional mBlk parameters are not NULL, it sets the
mBlk.mBlkHdr.mData and mBlk.mBlkHdr.mLen fields to indicate the location
and size of the corresponding data-link layer addresses. The additional mBlk
parameters are:
pSrc
The local source address of the frame.
pDst
The local destination of the frame.
pESrc
The original link-level source address, or the pSrc settings if none.
pEDst
The final link-level destination address, or the pDst settings if none.

NOTE: The endLib library contains a routine for retrieving address values from
Ethernet frame headers. Thus, you probably do not need to implement this routine
if your driver runs over Ethernet.

The endAddrGet( ) prototype is:


STATUS endAddrGet
(
M_BLK_ID pData, /* mBlk chain containing frame */
M_BLK_ID pSrc, /* local source address, in an mBlk */
M_BLK_ID pDest, /* local destination address, in an mBlk */
M_BLK_ID pESrc, /* actual source address, in an mBlk */
M_BLK_ID pEDest /* actual destination address, in an mBlk */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

endPacketDataGet( )

This routine parses an incoming frame provided in an mBlk chain. It places the
address information, including the size and offset of the address information, the

486
21 Integrating a New Network Interface Driver
21.6 Understanding END Implementation

offset of the frame payload, and the frame type, in the LL_HDR_INFO structure that
is passed in as a parameter.

NOTE: The endLib library contains a routine for retrieving the address and data
offsets and sizes and the type information from Ethernet frames. Thus, you
probably do not need to implement this routine if your driver runs over Ethernet.

The endPacketDataGet( ) prototype is:


STATUS endPacketDataGet
(
M_BLK_ID pData, /* mBlk chain containing packet */
LL_HDR_INFO * pHeader /* structure to hold header info */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

endIoctl( )

An END may need to support ioctl commands, particularly if it is to be used with


the existing IP network service sublayer. See Table 21-4 for a list of commonly used
ioctl commands.

! WARNING: If you are porting a driver from the BSD 4.3 model, you might be
tempted to use the existing xxIoctl( ) routine as your endIoctl( ) routine, skipping
the creation of separate routines for the multicast address table maintenance
routines. Do not do this! Your driver must implement the multicast address table
maintenance routines.

NOTE: Wind River reserves command constants (such as EIOCGFBUF) that are in
the range of 0-128. If you want to use your own custom ioctl commands, define
their command constants to be equivalent to numbers outside this range.
21
The endIoctl( ) routine takes the following arguments:

the unique interface identifier returned from the muxDevLoad( ) call

the ioctl command being issued

a buffer for additional data given in the command or for data to be returned
on completion of the command (defined as a caddr_t structure)

487
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 21-2 ioctl Commands and Data Types

Command Routine Data Type

EIOCSFLAGS Set device flags. See flags in int


B.3.3 END_OBJ, p.594.
EIOCGFLAGS Get device flags. int
EIOCSADDR Set device address. char *
EIOCGADDR Get device address. char *
EIOCMULTIADD Add multicast address. char *
EIOCMULTIDEL Delete multicast address. char *
EIOCMULTIGET Get multicast list. MULTI_TABLE *

EIOCGFBUF Get minimum first buffer for int


chaining.
EIOCQUERY Retrieve the bind routine. END_QUERY *

EIOCGHDRLEN Get the size of the datalink header. int


EIOCGMIB2 Get MIB-II counters from the driver. M2_INTERFACETBL *
EIOCGMIB2233 Get RFC 2233 MIB structure. M2_ID **

EIOCGPOLLCONF Get statistics polling configuration. END_IFDRVCONF **

EIOCGPOLLSTATS Get polled statistics counts. END_IFCOUNTERS **

The endIoctl( ) prototype is:


int endIoctl
(
END_OBJ * pEND, /* END Object */
int command, /* ioctl command */
caddr_t buffer /* holds response from command */
)

This routine returns 0 (zero) if successful, an appropriate error value otherwise, or


EINVAL if the command is not supported.

488
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

21.7 Understanding NPT Driver Implementation


This section presents an overview of how an NPT driver operates followed by
implementation recommendations for the standard NPT driver entry points. If
you compare this section with 21.6 Understanding END Implementation, p.473, you
will notice a strong parallelism. This arises from the fact that the NPT is a
packet-oriented equivalent to the END. Thus, the implementation
recommendations for both NPT drivers and ENDs are nearly identical. The few
differences that do exist are critical.
Currently, the Wind River Network Stack does not include an NPT driver
implementation, only END implementations. As a starting point for an NPT
driver, you might want to use the generic END defined in templateEnd.c.

NOTE: The design situations that require an NPT driver instead of an END are
rare. If you are writing a new driver, think first of implementing it as an END, for
which there exists a template as well as working driver implementations that you
can study. If porting a packet-oriented driver, feel free to port it as an NPT driver.
The Wind River Network Stack supports mixing the two driver styles.

21.7.1 NPT Driver Operation

This subsection presents an overview of the following NPT driver operations:



adding an NPT Driver to the Wind River Network Stack

launching an NPT Driver

responding to a service bind event

receiving frames
For the most part, the NPT and the END handle these operations identically. The
major exception is in the area of receiving frames. NPT drivers pass up information
21
which makes it easy to strip the datalink header, but the header is still present
when the NPT driver passes a received frame to the MUX.

NOTE: For instructions on starting additional drivers at run-time, see 20.2 Working
with Network Driver Instances, p.432.

489
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Adding an NPT Driver

Adding your driver is much like adding any other application to a target image.
The first step is to compile and include the driver code in the image.
Because the Wind River Network Stack allows you to create more than one
network device, you must set up a table that groups the #define configuration
statements for these devices into device-specific groups. This table, endDevTbl, is
defined in the configNet.h file in your target/config/bspname directory where
bspname is the name of your board support package, such as mv162 or pc486. For
example, to add an ln7990 NPT driver, edit configNet.h to contain lines such as:
/* Parameters for loading ln7990 NPT driver supporting buffer loaning. */
#define LOAD_FUNC_0 ln7990nptLoad
#define LOAD_STRING_0 "0xfffffe0:0xffffffe2:0:1:1"
#define BSP_0 NULL

Define three constants, like those shown above, for each of the devices you want to
add. To set appropriate values for these constants, consider the following:
LOAD_FUNC
Specifies the name of your driver’s nptLoad( ) entry point. For example, if your
driver’s nptLoad( ) entry point were ln7990nptLoad( ), you would edit
configNet.h to include the line:
#define LOAD_FUNC_n ln7990nptLoad
LOAD_STRING
Specifies the initialization string passed into muxDevLoad( ) as the initString
parameter. This string contains information that is passed blindly to the
driver’s nptLoad( ) routine. Its contents depend on what the driver expects.
You must also edit the definition of the endDevTbl (a table in configNet.h that
specifies the drivers included in the image) to list the devices to be loaded:
END_TBL_ENTRY endDevTbl [] =
{
{ 0, LOAD_FUNC_0, LOAD_STRING_0, BSP_0, NULL, FALSE },
{ 1, LOAD_FUNC_1, LOAD_STRING_1, BSP_1, NULL, FALSE },
...
{ 0, END_TBL_END, NULL, 0, NULL, FALSE },
};

The first number in each table entry specifies the unit number for the device. The
first entry in the example above specifies a unit number of 0. Thus, the device it
loads is deviceName0. The FALSE at the end of each entry indicates that the entry
has not been processed. After the system successfully loads a driver, it changes this
value to TRUE in the run-time version of this table. To prevent the system from
automatically loading your driver, set this value to TRUE.

490
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

After constructing these entries in configNet.h, you are ready to rebuild the
Wind River Network Stack to include your new drivers. When you boot this
rebuilt image, the system calls muxDevLoad( ) for each device specified in the
table in the order listed.

NOTE: The endDevTbl[ ] can contain a mix of NPT drivers and ENDs.

Launching the Driver

At system startup, the Wind River Network Stack spawns the user root task to
initialize the network. The task calls muxDevLoad( ), which calls the nptLoad( )
routine in your driver. The nptLoad( ) routine creates and partially populates an
END_OBJ structure and a NET_FUNCS structure. The END_OBJ structure describes
the driver to the MUX. The NET_FUNCS structure provides the MUX with
references to the MUX-callable driver routines.
After muxDevLoad( ) loads your driver, a muxDevStart( ) call executes the
nptStart( ) routine in your driver. The nptStart( ) routine should activate the driver
and register an interrupt service routine for the driver with the appropriate
interrupt connect routine for your architecture and BSP.

Responding to Network Service Bind Calls

A driver is not required to respond when a service binds to a device. If you want
your driver to respond to a bind event, your driver can support an nptBind( )
routine. When a service binds to an interface controlled by your driver, the MUX
uses the driver’s nptIoctl( ) routine to retrieve a pointer to that driver’s nptBind( )
routine (if any). The MUX then executes that routine before continuing with the
bind.
21
To get a pointer to a driver’s nptBind( ), the MUX issues an EIOCQUERY command
to the driver’s nptIoctl( ) routine. As input, the call supplies an END_QUERY
structure whose members are used as follows:
query
Set by MUX to END_BIND_QUERY.
queryLen
Set by MUX to the expected size of the data in queryData.
queryData
Set by your driver’s nptIoctl( ) to point to the driver’s nptBind( ).

491
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Receiving Frames

When an interrupt is received, the Wind River Network Stack invokes the
interrupt service routine that was registered by the nptStart( ) routine. This
interrupt service routine should do the minimum amount of work necessary to
transfer the frame from the local hardware into accessible memory (ideally a
cluster: see 21.3.3 The Data-Link-to-MUX Interface, p.461).
To minimize interrupt lockout time, the routine should handle at interrupt level
only those tasks that require minimum execution time, such as error checking or
device status change. The routine should queue all time-consuming work for
processing at task level.
To queue frame reception work for processing at the task level, use the
netJobAdd( ) routine. This routine takes a routine pointer and up to five additional
arguments (representing parameters to the routine referenced by the routine
pointer). The netJobAdd( ) routine prototype is:
STATUS netJobAdd
(
FUNCPTR routine,
int param1,
int param2,
int param3,
int param4,
int param5
)

The routine in this case should be the routine in your driver that completes frame
processing at the task level. The netJobAdd( ) routine puts the job request on
tNetTask’s work queue and gives the appropriate semaphore that awakens
tNetTask.
Upon awakening, tNetTask dequeues routine calls and associated arguments
from its work queue. It then executes these routines in its context until the queue
is empty.
Your task-level frame reception routine should do whatever is necessary to
construct an mBlk chain containing the frame to hand off to the MUX, such as
assuring data coherency. This routine should also set M_MCAST and M_BCAST
flags in the mBlk header if appropriate. When all is ready, your driver passes the
frame up to the MUX by calling the routine referenced as the receiveRtn field of
the END_OBJ structure representing your device.

492
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

To deliver a packet to the stack, NPT driver's receive routine calls a function
pointer set by the MUX, using the TK_RCV_RTN_CALL( ) macro defined in
endLib.h. This macro takes arguments as if it were a routine declared just like
muxTkReceive( ). See sections 21.4 How ENDs and NPT Drivers Differ, p.462, and
B.2.23 muxTkReceive( ), p.590, for more information on the arguments passed to
this routine.

21.7.2 NPT Driver Interface to the MUX

This subsection describes the driver entry points and the shared data structures
that comprise the NPT driver’s interface to the MUX.

Data Structures Used by the Driver

The core data structure for an NPT driver is the END object, or END_OBJ. The
structure is defined in target/h/end.h (see also B.3.3 END_OBJ, p.594). The driver’s
load routine returns a pointer to an END_OBJ that it allocated, zeroed out, and
partially populated. This structure supplies the MUX with information that
describes the driver as well as a pointer to a NET_FUNCS structure populated with
references to the NPT’s standard entry points.
Although the driver’s load routine is responsible for populating much of the
END_OBJ structure, some of its members are set within the MUX when a protocol
binds to the device. Specifically, the MUX maintains the array of protocols bound
to the END_OBJ. When the driver calls its registered receive routine (usually an
indirect call to muxTkReceive( ) for an NPT driver), this routine calls the bound
protocol receive routines appropriate for the received packet.

NPT Driver Entry Points Exported to the MUX 21

Table 21-3 lists the standard driver entry points that the NET_FUNCS structure
exports to the MUX. In this manual, the routines use a generic “npt” prefix, but in
practice this prefix is usually replaced with a driver-specific identifier, such as
"ln7990" for the Lance Ethernet driver.

493
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 21-3 NPT Driver Routines

Routine Description

nptLoad( ) Load a device into the MUX and associate a driver with
the device.

nptUnload( ) Release a device, or a port on a device, from the MUX.

nptBind( ) Exchange data with the protocol layer at bind time.


(Optional)

nptSend( ) Accept data from the MUX and send it on to the physical
layer.

nptMCastAddrDel( ) Remove a multicast address from those registered for the


device.

nptMCastAddrGet( ) Retrieve a list of multicast addresses registered for a


device.

nptMCastAddrAdd( ) Add a multicast address to the list of those registered for


the device.

nptPollSend( ) Send packets in polled mode rather than interrupt-driven


mode.

nptPollReceive( ) Receive frames in polled mode rather than


interrupt-driven mode.

nptStart( ) Connect device interrupts and activate the interface.

nptStop( ) Stop or deactivate a network device or interface.

nptIoctl( ) Support various ioctl commands.

nptLoad( )

Before you can use a network interface to send and receive frames, you must load
the appropriate device driver into the MUX and then configure that driver for the
interface. The user root task loads network device drivers into the MUX by calling
muxDevLoad( ) for all the drivers referenced in endDevTbl[ ]. The entries in this
table provide all the information needed to call muxDevLoad( ). This includes the
actual name of your driver’s nptLoad( ) routine.

494
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

As input, the nptLoad( ) routine takes an initialization string. The contents of this
string are user-defined but generally include such items as the unit number
identifying the physical interface8, an interrupt vector number, and the address of
memory mapped registers.
You must write your nptLoad( ) routine as a two-pass algorithm. The MUX calls it
twice during the load procedure. In the first pass, it calls your nptLoad( ) routine
using a blank (all zeros) initialization string. Your nptLoad( ) routine is expected to
check for the blank string and return with the name of the device copied into the
string.
The MUX then calls your nptLoad( ) a second time using the actual initialization
string that was supplied to muxDevLoad( ). Your nptLoad( ) routine must then
return a pointer to the END_OBJ that it allocates, or a NULL if the load fails.
Typically, the nptLoad( ) routine, in its second pass, does the following:
■ Initialize the device and interface.
■ Allocate, zero out, and fill the END_OBJ structure.
■ Initialize any necessary private structures.
■ Parse and process the initialization string.
■ Create and initialize a private pool of memory using the API in netBufLib.
■ Allocate one or more network buffer pools using netBufLib.
■ Create and populate the MIB II interface table.
■ Fill the NET_FUNCS table referenced by pNetFuncs in the END_OBJ structure.
The nptLoad( ) routine is based on the following skeleton:
END_OBJ * nptLoad
(
char * initString, /* defined in endTbl */
void * pBsp /* BSP-specific information (optional) */
)
{
END_OBJ * newEndObj;
if( !initString ) /* initString is NULL, error condition */ 21
{
/* set errno perhaps */
return ((END_OBJ *) ERROR);
}

8. Although a driver is only loaded once, the driver’s nptLoad( ) routine is called for
each port to be activated within the driver. This lets the MUX allocate an entry for
each port. The MUX interface does not impose restrictions on how drivers handle
multiple ports as long as the driver allocates a separate END_OBJ for each port.

495
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

else if( initString[0] == 0 ) /* initString[0] is NULL, pass one */


{
strcpy( initString, "foo" );
return (END_OBJ *) NULL;
}
else /* initString is not NULL, pass two */
{
/* initialize device */
newEndObj = (END_OBJ *) malloc( sizeof(END_OBJ) );
/* fill newEndObj and newEndObj->pFuncTable */
/* call endM2Init() to initialize MIB interface data */
/* initialize any needed private structures */
/* parse and process initString, and pBsp if necessary */
/* create a private pool of memory using netBufLib API */
/* create network buffer pools using netBufLib API */
return( newEndObj );
}
}

nptUnload( )

The MUX calls your driver’s nptUnload( ) when a system application calls
muxDevUnload( ). In its nptUnload( ), your driver is responsible for doing
whatever it takes to “release” the device. It should also free the memory allocated
for the END object.
The MUX calls your driver’s nptUnload( ) for each port that has been activated by
a call to the driver’s nptLoad( ). If the device has loaded multiple ports, the driver’s
nptLoad( ) must not free up any shared resources until an unload request has been
received for each of the loaded ports.
The nptUnload( ) routine does not need to notify services about unloading the
device. Before calling nptUnload( ), the MUX first sends a shutdown notice to each
service attached to the device.
The nptUnload( ) prototype is:
STATUS nptUnload
(
END_OBJ * pEND /* END object */
)

nptBind( )

The nptBind( ) routine is an optional driver routine that gives your driver the
ability to respond to bind events. Using nptBind( ), your driver can support the
exchange of information between a service and a driver whenever the service
binds to a device through that driver.

496
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

The MUX calls your driver’s nptBind( ) routine (if any), in response to bind events
through that driver. To get an executable reference to a driver’s nptBind( ) routine,
the MUX uses the driver’s nptIoctl( ) routine.
The MUX calls nptBind( ) while processing a bind request from the network
service. Arguments passed to nptBind( ) include:

a reference to information supplied by the network service
(although the network service may choose to supply no information at all)
■ a reference to a template for network driver information
(if your driver cares to provide any)
■ the network service type
The routine is expected to return OK if the bind request is accepted. The driver may
also reject the bind request by returning ERROR, in which case the MUX will deny
the bind request to the network service.
The nptBind( ) prototype is:
STATUS nptBind
(
END_OBJ * pEND, /* END object */
void * pNetSvcInfo, /* info provided by the network service */
void * pNetDrvInfo, /* template for network driver info */
long type /* of network service trying to bind */
)

nptSend( )

The network driver send routine is referenced from the NET_FUNCS table. The
MUX calls this routine when the network service issues a send request. The send
routine is supplied a reference to an mBlk chain representing the packet to be sent.
This routine should prepend the link-level header to the packet (for information on
making this more efficient, see 21.4.3 Early Link-Level Header Allocation in an NPT
Driver, p.465). 21
The nptSend( ) prototype is:
STATUS nptSend
(
END_OBJ * pEND, /* END object */
M_BLK_ID pMblk, /* network packet to transmit */
char * dstAddr, /* destination MAC address */
int netSvcType, /* network service type */
void * pSpare /* optional network service data */
)

497
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This routine should return a status OK if the send was successful,


END_ERR_BLOCK if the send could not be completed because of a transient
problem such as insufficient resources, or ERROR (in which case, errno should be
set appropriately).

nptMCastAddrAdd( )

This routine registers a physical-layer multicast address with the device. As


arguments, it takes:
■ a pointer to the END_OBJ structure returned by nptLoad( )
■ a string containing the physical address to be added
(or a reference to the address)
This routine should reconfigure the interface in a hardware-specific way that lets
the driver receive frames from the specified address and pass those frames along.
The nptMCastAddrAdd( ) prototype is:
STATUS nptMCastAddrAdd
(
END_OBJ * pEND, /* driver's control structure */
char * pAddress /* physical address or a reference thereto */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

nptMCastAddrDel( )

This routine removes a previously registered multicast address from the list
maintained for a device. It takes as arguments a pointer to the END_OBJ structure
returned by nptLoad( ), and a string containing the physical address to be removed
or a reference to that address.
The nptMCastAddrDel( ) prototype is:
STATUS nptMCastAddrDel
(
END_OBJ * pEND, /* END object */
char * pAddress /* physical address, or a reference to it */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

498
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

nptMCastAddrGet( )

This routine retrieves a list of all multicast addresses that have been registered
with the device. It takes as arguments a pointer to the END_OBJ structure returned
by nptLoad( ), and a pointer to a MULTI_TABLE structure into which the list will
be put.
The nptMCastAddrGet( ) prototype is:
STATUS nptMCastAddrGet
(
END_OBJ * pEND, /* END object */
MULTI_TABLE * pMultiTable /* container for address list */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

nptPollSend( )

This routine provides a polled-mode equivalent to the driver’s interrupt-driven


send routine. Either it must transfer a frame directly to the underlying device, or it
must exit immediately if the device is busy or resources are unavailable.

NOTE: Poll mode should only be used for debugging. For details, see Polled Mode,
p.456.

NOTE: When the system calls your nptPollSend( ) routine, it is probably in a mode
that cannot service kernel calls. Therefore, this routine must not perform any
kernel operations, such as taking a semaphore or allocating memory. Likewise, this
routine should not block or delay because the entire system might halt.

Within your nptPollSend( ) routine, verify that the device has been set to
polled-mode (by a previous nptIoctl( ) call). Your nptPollSend( ) routine should
then put the outgoing packet directly onto the network, without queuing the 21
packet on any output queue.
This routine takes as arguments a pointer to the END_OBJ structure returned by
nptLoad( ), a reference to an mBlk or mBlk chain containing the outgoing packet,
a pointer to a buffer containing the destination MAC address, the network service
type (in network byte order), and a pointer to optional additional data (or NULL).
Like the nptSend( ) routine, the nptPollSend( ) routine must add the link header.
However, it should not modify the M_BLK chain, which is owned by the caller.
Because the poll send routine is a low-performance interface used primarily for the
WDB connection, the driver typically copies the data contents of the passed mBlk
chain into a separate contiguous buffer following the constructed MAC header.

499
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The nptPollSend( ) prototype is:


STATUS nptPollSend
(
END_OBJ * pEND, /* END object */
M_BLK_ID pPkt, /* network packet to transmit */
char * dstAddr, /* destination MAC address */
long netType, /* network service type */
void * pSpareData /* optional network service data */
)

This routine should return OK if the packet was successfully transmitted, or


EAGAIN if the device cannot send the packet just yet. Do not set the errno variable.

nptPollReceive( )
This routine receives frames using polling instead of an interrupt-driven model.
The routine retrieves the frame directly from the network and copies it into the
provide mBlk passed to the routine. If no frame is available, it returns ERROR.

NOTE: When the system calls your nptPollReceive( ) routine, it is probably in a


mode that cannot service kernel calls. Therefore, this routine must not perform any
kernel operations, such as taking a semaphore or allocating memory. Likewise, this
routine must not block or delay because the entire system might halt.

Within the nptPollReceive( ) routine, verify that the device has been set to
polled-mode (by a previous nptIoctl( ) call). The routine should then retrieve the
frame directly from the network and copy it into the mBlk passed in to the routine.
It takes as arguments a pointer to the END_OBJ structure returned by nptLoad( )
and a reference to an mBlk or mBlk chain into which the incoming data should be
put, as well as information about the frame type and the offset within the packet
to the network frame.
The nptPollReceive( ) prototype is:
STATUS nptPollReceive
(
END_OBJ * pEND, /* END object */
M_BLK_ID pMblk, /* received frame */
long * pNetSvc, /* payload/network frame type */
long * pNetOffset, /* offset to network frame */
void * pSpareData /* optional network service data */
)

This routine should return OK or an error value of EAGAIN if the received data is
too large to fit in the provided mBlk, or if no data is available.

500
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

nptStart( )

The driver’s nptStart( ) routine connects device interrupts and makes the interface
active and available. This routine takes as its argument the END_OBJ structure
pointer returned from the nptLoad( ) call. As with nptLoad( ), this call is made for
each port that is to be activated within the driver.
The nptStart( ) prototype is:
STATUS nptStart
(
END_OBJ * pEND, /* END object */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

nptStop( )

The driver’s nptStop( ) routine halts a network device, typically by disconnecting


the appropriate interrupt. It does not remove the device by releasing the allocated
data structures. It takes as its argument the END_OBJ structure pointer returned
from the nptLoad( ) call.
The nptStop( ) prototype is:
STATUS nptStop
(
END_OBJ * pEND, /* END object */
)

This routine should return a status OK or ERROR (in which case, errno should be
set appropriately).

nptIoctl( )

An NPT driver must support the ioctl command defined as EIOCGNPT. This
command is used to determine if the driver is of the NPT variety. All the driver 21
needs to do upon receiving this command is to return 0 (zero), indicating success.
For other drivers, this ioctl command is undefined and therefore returns EINVAL,
indicating that it is not an NPT driver.
Like an END driver, an NPT driver should support the EIOCGMIB2 and
EIOCGMIB2233 commands by calling the endM2Ioctl( ) routine.
An NPT driver may also need to support other ioctl commands, particularly if it is
to be used with the existing IP network service sublayer. See Table 21-4 for a list of
commonly used ioctl commands.

501
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table 21-4 ioctl Commands and Data Types

Command Routine Data Type

EIOCSFLAGS Set device flags. See flags in int


B.3.3 END_OBJ, p.594.

EIOCGFLAGS Get device flags. int

EIOCSADDR Set device address. char *

EIOCGADDR Get device address. char *

EIOCMULTIADD Add multicast address. char *

EIOCMULTIDEL Delete multicast address. char *

EIOCMULTIGET Get multicast list. MULTI_TABLE *

EIOCPOLLSTART Set device into polled mode. NULL

EIOCPOLLSTOP Set device into interrupt mode. NULL

EIOCGFBUF Get minimum first chaining buffer. int

EIOCGNPT Indicate NPT-compliance. void

EIOCQUERY Retrieve the bind routine. END_QUERY *

EIOCGHDRLEN Get the size of the datalink header. int

EIOCGMIB2 Retrieve RFC 1213 MIB-II table. M2_INTERFACETBL *

EIOCGMIB2233 Get RFC 2233 MIB structure. M2_ID **

EIOCGPOLLCONF Get statistics polling configuration. END_IFDRVCONF **

EIOCGPOLLSTATS Get polled statistics counts. END_IFCOUNTERS **

NOTE: Command constants (such as EIOCGFBUF) in the range of 0-128 are


reserved for use by Wind River. If you want to use your own custom ioctl
commands, you should define their command constants to be equivalent to
numbers outside of this range.

502
21 Integrating a New Network Interface Driver
21.7 Understanding NPT Driver Implementation

The nptIoctl( ) routine takes three arguments:



the END_OBJ pointer returned from the nptLoad( ) call

the ioctl command being issued

a buffer for additional data given in the command or for data to be returned
on completion of the command (defined as a caddr_t structure)

! WARNING: If you are porting a driver from the BSD 4.3 model, you might be
tempted to use the existing xxIoctl( ) routine as your nptIoctl( ) routine, skipping
the creation of separate routines for the multicast address table maintenance
routines. Do not do this! Your driver must implement the multicast address table
maintenance routines.

The nptIoctl( ) prototype is:


int nptIoctl
(
END_OBJ * pEND, /* END object */
int command, /* ioctl command */
caddr_t buffer /* holds response from command */
)

This routine returns 0 (zero) if successful, an appropriate error value otherwise, or


EINVAL if the command is not supported.
In the case where command is set to EIOCQUERY, the buffer will be set to point to an
END_QUERY structure. The query field of this structure will be set to the type of
query (for instance, END_BIND_QUERY), and the queryLen field will be set to the
size of the queryData buffer. Upon receipt of an EIOCQUERY command, you
should respond either by copying data into this queryData buffer, or by returning
an error value such as EINVAL from nptIoctl( ).
Your driver is not required to support EIOCQUERY commands, but you may find
this a useful way of communicating with the protocol layer.
21

503
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

21.8 Porting a BSD Driver to the MUX


To convert a BSD driver that communicates directly with the protocol layer into
one that communicates with the protocol layer through the MUX, you need to
make the following changes:

remove unit number references

create an END Object to represent the device

implement the standard END or NPT entry points
When deciding whether to implement an END or NPT driver, choose the interface
style that is most convenient for the driver you are porting. If you are porting a
frame-oriented driver, the END is likely to be the more convenient driver style.

21.8.1 Remove Unit Number References

Under the MUX, each device is independent. Your BSD model may consider each
device to be part of an array of devices, each with a unit number. BSD driver
routines are sometimes written to take unit numbers as parameters, and to
distinguish between devices based on these unit numbers. In the MUX model, the
END Object is the distinguishing feature of devices, and MUX routines distinguish
between devices based on the END Object pointer that is passed in to the routines.

21.8.2 Create an END Object to Represent the Device

The head of your driver control object should be an END_OBJ structure that
includes all hardware- and driver-specific elements.

21.8.3 Implementing the Standard END or NPT Entry Points

The END and NPT models for network interface drivers contain standard entry
points that are not present in the BSD model. Table 21-5 shows some of the
analogies. You should be able to reuse much of the code from the BSD driver.

! CAUTION: When porting a BSD network driver to the MUX, you must replace all
calls into the protocol with appropriate calls into the MUX. In addition, you must
remove all code that implements or uses etherInputHook( ) or
etherOutputHook( ) routines.

504
21 Integrating a New Network Interface Driver
21.8 Porting a BSD Driver to the MUX

Table 21-5 Required Driver Entry Points and their Derivations

NPT or END Entry Points BSD 4.3 Style Entry Points

xLoad( ) xxattach( )

xUnload( ) None – see endUnload( ), p.480, or nptUnload( ), p.496,


and templateEnd.c.

N/A xxReceive( )

xSend( ) xxOutput( )

xIoctl( ) xxIoctl( )

xMCastAddrAdd( ) None – see endMCastAddrAdd( ), p.481, or


nptMCastAddrAdd( ), p.498, and templateEnd.c.

xMCastAddrDel( ) None – see endMCastAddrDel( ), p.482, or


nptMCastAddrDel( ), p.498, and templateEnd.c.

xMCastAddrGet( ) None – see endMCastAddrGet( ), p.482, or


nptMCastAddrGet( ), p.499, and templateEnd.c.

xPollSend( ) N/A – see endPollSend( ), p.483, or nptPollSend( ), p.499,


and templateEnd.c.

xPollReceive( ) N/A – see endPollReceive( ), p.483, or nptPollReceive( ),


p.500.

xStart( ) N/A – see endStart( ), p.484, or nptStart( ), p.501.

xStop( ) N/A – see endStop( ), p.485, or nptStop( ), p.501.

endAddressForm( )a N/A – see also endAddressForm( ), p.485.


21
endAddrGet( )a N/A – see also endAddrGet( ), p.486.

endPacketDataGet( )a N/A – see also endPacketDataGet( ), p.486.


a. These routines are implemented for Ethernet in endLib. If porting the BSD driver to run
over Ethernet, you probably do not need to implement these routines.

505
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Rewrite xxattach( ) to Use an npt/endLoad( ) Interface

Rewrite the interface of your xxattach( ) to match the npt/endLoad( ) routine


described in nptLoad( ), p.494, or endLoad( ), p.479.
Much of the code that handles the specifics of hardware initialization should be the
same. When allocating the memory for packet reception buffers that are passed up
to the service, you should use the MUX buffer management utilities. See
21.4.1 Managing Memory for Network Drivers and Services, p.464, 3. Configuring and
Managing Memory as well as the reference entry for muxBufInit( ).
Remove any code your xxattach( ) included to support the implementation of the
etherInputHook( ) and etherOutputHook( ) routines. Etherhooks are no longer
supported. Similar functionality is now provided using BPF (see 20.6 Adding a BPF
Device, p.453).
You may also need to add code that clears out the MIB2 variables in the END
Object’s mib2Tbl structure.

The xxReceive( ) Routine Still Handles Task-Level Packets

Because the MUX does not directly call the driver’s packet reception code, there is
no npt/endReceive( ) entry point. Your driver still needs to handle packet reception
at the task level. Unfortunately, most of the code in this driver routine will require
extensive revision. Instead of calling the service directly, this routine uses a
MUX-supplied routine to pass a packet up to the service. Likewise, your receive
routine should use a MUX-managed memory pool as its receive buffer area.

Rewrite xxOutput( ) to Use an npt/endSend( ) Interface

Rewrite the interface of your output routine to match the npt/endSend( ) entry
point described in nptSend( ), p.497 or endSend( ), p.481.
Much of the code that dealt directly with putting the packet on the hardware
should need little if any revision. You should change your code to use mBlk chains
allocated out of a netBufLib-managed memory pool. See the reference entry for
netBufLib for details.

506
21 Integrating a New Network Interface Driver
21.9 Supporting Multiple Network Interface Drivers

The xxIoctl( ) Routine is the Basis of npt/endIoctl( )

Rewrite the interface of your xxIoctl( ) to match the npt/endIoctl( ) routine


described in nptIoctl( ), p.501 or endIoctl( ), p.487. If your driver used xxIoctl( ) to
implement multicasting, you must break that functionality out into the separate
npt/endMCastAddrAdd( ), npt/endMCastAddrDel( ), and
npt/endMCastAddrGet( ) entry points.

Implement All Remaining Required END or NPT Entry Points

Table 21-5 lists a handful of driver points unique to ENDs and NPT drivers. Both
an END and an NPT require you to implement the xSend( ), xStart( ), and xStop( )
entry points. There are no BSD equivalents for these entry points. In addition, if
you are implementing an END, you must implement entry points for
endAddressForm( ), endAddrGet( ), and endPacketDataGet( ). These routines are
already implemented for Ethernet in endLib. If your driver will run over Ethernet,
you may use the routines supplied in endLib.

21.9 Supporting Multiple Network Interface Drivers


The Wind River Network Stack allows you to use multiple network interface cards
simultaneously. You can use multiple cards of the same variety, or different types
of cards, with a combination of END and NPT drivers.9

Configuring for Multiple Drivers

To configure the Wind River Network Stack to support multiple drivers, make 21
sure that the drivers are compiled into your image. Follow the directions in Adding
an NPT Driver, p.490 (for an NPT driver) or Adding an END, p.473 (for an END).
You may also need to increase the value of the configuration parameters
IP_MAX_UNITS and MUX_MAX_BINDS.

9. Some BSPs and drivers may have their own limitations on the number of interfaces and
units they support.

507
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Starting Additional Drivers at Run-Time

To start additional network interfaces manually at run-time:


1. Use muxShow( ) to display information on each currently loaded interface.
When adding a new interface, you do not want to conflict with any interface
already loaded. The routines ifShow( ) and ifconfig( ) display information on
interfaces to which the IPv4 or IPv6 protocols have been attached.
2. Use muxDevLoad( ) to load the driver for the network interface.
3. Use muxIfFuncAdd( ) to install any routines particular to the relationship
between a particular interface type and a particular protocol. You can use this
routine to assign an address resolution routine, a multicast address resolution
routine, or an output routine.
If you loaded an Ethernet driver over which you do not intend to do
multicasting, you can probably skip this step. Drivers that register as Ethernet
drivers automatically use arpresolve( ) and other appropriate generic defaults.
Similarly, if you are working with either of the supplied pseudo devices, stf or
gtf, you can skip this step. It is handled automatically when the tunnel library
is initialized.
4. Use muxDevStart( ) to initialize the network interface.
5. Use muxTkBind( ) to bind the driver to the service. In the case of IPv4, the
binding is handled automatically in the ipAttach( ) routine. For IPv6, use
ip6Attach( ) routine.
6. Configure the interface. This means assigning an IP address and a netmask
(IPv4) or prefix IPv6). Use ifconfig( ). Assign an IPv4 or IPv6 address
depending on which sort of packet you want to exchange through the device.
When you call ifconfig( ) to bring up inet6, this triggers IPv6 link-local
address generation for the interface.
7. Bring up the link state and protocol state of the interface using the up, link up,
inet6 up, and inet up options in an ifconfig( ) call. To bring up the both the
link and protocol (both IPv4 and IPv6) states, use the global up option. For
example:
-> ifconfig "fei0 up"

To separate out each aspect of the global up shown above, you would need to
do the following:
-> ifconfig "fei0 link up"
-> ifconfig "fei0 inet up"
-> ifconfig "fei0 inet6 up"

508
21 Integrating a New Network Interface Driver
21.10 Avoiding Memory Leaks

If you do not want to bring up both the IPv4 and IPv6 functionality for the
interface, omit the inet up or inet6 up calls as needed.
8. Check that the interface was loaded and configured correctly:

ifShow( ) – list configuration information for network devices

routec( ) – check that the routing table has an entry for the device

NOTE: For information on the exact inputs expected by the routines named above,
see the relevant reference entries.

21.10 Avoiding Memory Leaks


Your driver implementation may allocate a semaphore during its initialization
phase and store a reference to it in the END object’s txSem field. For example,
endObjInit( ), which is commonly used to initialize an END, does this. 10
If this semaphore is not deleted when the driver is unloaded, a memory leak will
result equal to the size of the semaphore data structure plus any memory
allocation overhead.
This may not be an issue for your application (the amount of memory that leaks is
small), but if drivers are loaded and unloaded frequently, this could add up and
become a problem.

21

10. Note that endObjInit( ) is an actual routine defined in endLib.c. It is not an END entry
point, which would have been indicated as endObjInit( ).

509
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

510
22
Integrating a New Network
Service

22.1 Introduction 511


22.2 Writing a Network Service Sublayer 512
22.3 Interfacing with the MUX 516
22.4 Adding a Socket Interface to Your Service 520

22.1 Introduction
This chapter describes how to integrate a new network service with Wind River
Network Stack. A network service, such as a network protocol, is an
implementation of the network and transport layers of the OSI network model.
As shown in Figure 21-1, network services communicate with the data link layer
through the MUX interface. Part of porting a new network service to the
Wind River Network Stack is porting its data link layer access code to use the MUX
interface. Everything specific to the network interface is handled in the drivers of
the data link layer, which are described in 21. Integrating a New Network Interface
Driver.

NOTE: Currently, well-known service port numbers and other such information is
hard coded in services.c. There is no API that you can use to add information to
this file for the new services that you create.

511
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

22.2 Writing a Network Service Sublayer


A network service sublayer allows a network service to send and receive packets
through the MUX. It may be written as part of a network service, or as a separate
element that the service uses. The minimum requirements of a network service
sublayer are an initialization routine and routines that support packet transfer and
error reporting. Support for flow control is optional.

22.2.1 Initializing the Interface

When the system constructs the network stack, it activates network interfaces that
include a network service and a network driver. The activation routine that you
provide in your network service sublayer, by convention, is named fooAttach( ),
where foo is replaced by an abbreviation for the network service. This naming
convention is a generalization based on the name of ipAttach( ). Your fooAttach( )
routine typically allocates and initializes data structures that represent the
interface being attached to, determines the network driver paradigm (END or
NPT), and binds to the driver interface through the MUX.

Determining the Driver Paradigm

To determine a driver’s operating paradigm, use the muxTkDrvCheck( ) routine


(see B.2.20 muxTkDrvCheck( ), p.588). If your network service has not been written
to accommodate ENDs, its fooAttach( ) routine should return an error if
muxTkDrvCheck( ) does not return TRUE.

The Bind Phase

The network service must bind to a driver before it can send and receive packets
through it. Binding to a network driver is accomplished by calling the
muxTkBind( ) routine (see B.2.19 muxTkBind( ), p.586).
The protocol type supplied to the bind routine is used by the MUX to prioritize the
services, and determines which service sees which packets. A
MUX_PROTO_SNARF type service sees all the packets that are processed by any
driver to which it is bound. A MUX_PROTO_PROMISC type service sees a packet
only after all other services bound to a driver have had a chance to consume it. A
MUX_PROTO_OUTPUT type service sees outgoing rather than incoming packets.

512
22 Integrating a New Network Service
22.2 Writing a Network Service Sublayer

After the bind operation has completed successfully, the sublayer should
determine which (if any) registered service address mapping routines are relevant
to the network interface. The sublayer should obtain references to those that apply
and retain these references for later use within the interface.

Network Address Resolution Routine

The address resolution routine translates a network service address to a network


driver (physical layer) address. To find the address resolution routine that applies
to a specific network service/network driver pair, use the muxAddrResFuncGet( )
routine (see B.2.5 muxAddrResFuncGet( ), p.580).
Typically, the network service performs address resolution when it sends a packet
to the network driver. The sublayer uses the address resolution routine obtained
in this step to resolve the address. If an address resolution routine does not exist
for this combination of service and driver, the network service is not expected to
initiate the address resolution. This allows flexibility for those services that prefer
to have the address resolution performed by the network driver.
If the address resolution mechanism qualifies as an address resolution protocol
(for instance, ARP) or network service in itself, it should bind to the MUX as a
distinct service. Typically, it would bind itself to the same interface to which the
corresponding network service is bound. The address resolution mechanism could
even share the same callback routines of the network service if it knows how to
distinguish between the two services.
The network address resolution routine also supports multicast mapping, and
maps a network service multicast address to a network driver (physical layer)
multicast address.

22.2.2 Data Structures and Resources

The network service sublayer may allocate buffer pools in the form of mBlk
clusters for receiving and sending packets. The network buffer management 22
library netBufLib facilitates the implementation of an effective scheme for this
purpose. The sublayer may also make use of the system mBlk pools. For details,
see 21.4.1 Managing Memory for Network Drivers and Services, p.464, and
3. Configuring and Managing Memory.
Other resources commonly used by network services include receive/transmit
queues and data structures that represent each active network interface controlled
by the sublayer. Data that should be collected and maintained for each interface
includes:

513
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1


the network driver’s paradigm

the state of the interface (for instance: attached, stopped, flow-controlled)

the cookie supplied by the MUX, this cookie identifies the binding instance

references to the service address mapping routines for the interface

22.2.3 Sublayer Routines

The subsections provides an overview of how a network service sublayer handles:


■ sending packets
■ receiving packets
■ shutting down an interface
■ reporting errors
■ flow control
■ device control

Sending Packets

Network layer packets are sent down through the MUX by using the
muxTkSend( ) routine (see B.2.24 muxTkSend( ), p.591). Data to be sent arrives
from an upper layer in the form of an mBlk chain, and is modified by your
network service before being sent.
The muxTkSend( ) routine may return an error indicating that the driver is out of
resources and cannot transmit the packet. A network service can use this error to
establish a flow control mechanism (see Flow Control, p.516).

Sending Packets through an END

Sending packets through an END requires that the mBlk chain being sent contains
fully formed physical layer frames. If necessary, a protocol must use the address
resolution routine registered for the interface to determine the destination address,
and then use the muxAddressForm( ) routine to add the necessary frame header
to the packet.

Sending Packets through an NPT driver

When sending packets through an NPT driver, if the interface over which packets
are being sent has a registered address resolution routine, it should be called at
send-time and the resolved address should be passed into muxTkSend( ).

514
22 Integrating a New Network Service
22.2 Writing a Network Service Sublayer

Receiving Packets

The MUX forwards incoming packets to the appropriate network service by


invoking the stackRcvRtn( ) callback that was installed by the sublayer during the
bind phase (see stackRcvRtn( ), p.517).
By default, unless the network service is registered with the MUX as a SNARF or a
PROMISC service, the received packet starts with the network service header. Any
required physical-layer header information may be passed up using the optional
“piggy-back” facility in the stackRcvRtn( ) argument list.
If your stackRcvRtn( ) returns TRUE (except if your service is of type
MUX_PROTO_PROMISC), the packet is consumed and will not be available to
lower priority services listening to the same driver. If, on the other hand, your
routine returns FALSE (or is of type MUX_PROTO_PROMISC), the packet will
remain available to other services.
If your service has been registered as of type MUX_PROTO_OUTPUT, its
stackRcvRtn( ) callback routine is called for all packets going out over the driver
bound to your service. If the stackRcvRtn( ) of such an output protocol returns
TRUE, the packet is consumed by the protocol and will not go out over the driver.
If it returns FALSE, the outgoing packet will continue on to the driver. Only one
service at a time may bind with type MUX_PROTO_OUTPUT to any given driver.

Shutting Down an Interface

The MUX initiates a shutdown in response to a muxDevUnload( ) call from the


system. Before unloading the network driver, the MUX issues a shutdown
message to every network service bound to that driver by calling the
stackShutdownRtn( ) callbacks that were registered for those driver/service
interfaces at bind time (see stackShutdownRtn( ), p.517).
Within this shutdown routine, the network service must take the necessary steps
to close the interface, including a call to muxUnbind( ) to unbind the network 22
service from the device (see B.2.26 muxUnbind( ), p.592).

Error Reporting

Your network service may want to be notified of errors encountered in lower


layers of the stack. Error conditions encountered by a network driver are passed
up to the MUX. The MUX forwards each error to your network service sublayer if
a stackErrorRtn( ) callback is registered at bind time (see stackErrorRtn( ), p.518).

515
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Flow Control

The muxTkSend( ) routine may return an error, END_ERR_BLOCK, indicating that


the network driver has insufficient resources to transmit data1. The network
service sublayer can use this feedback to establish a flow control mechanism by
holding off on making any further calls to muxTkSend( ) until the device is ready
to restart transmission. At that time, the MUX calls the stackRestartRtn( ) that you
registered for the interface at bind time (see stackRestartRtn( ), p.518).

Device Control

A driver may be written to respond to specific ioctl commands. These commands


can be issued from your network service by calling muxIoctl( ) (see
B.2.15 muxIoctl( ), p.585).

22.3 Interfacing with the MUX


When a network service registers with the MUX, it must provide references to
routines that the MUX can call to handle the following:

shutting down the network service

passing a packet into the service

passing a error message into the service

restarting the service after a pause
The prototypes of the routines you specify to handle these routines differ
depending on whether you use muxTkBind( ) or muxBind( ) to bind the service to
a network interface in the MUX. If you are implementing a new network service,
you should use the muxTkBind( ) interface. This chapter includes the older
muxBind( ) interface solely to assist people maintaining network services that
were designed to work with ENDs before the development of the NPT.

1. Some less-carefully written drivers may simply return ERROR in this case, and it would not
be possible for your service to determine whether this was due to a temporary problem such
as insufficient resources or a more serious problem.

516
22 Integrating a New Network Service
22.3 Interfacing with the MUX

22.3.1 Service Routines Registered Using muxTkBind( )

This section describes the four service routines referenced in a muxTkBind( ) call.

stackShutdownRtn( )

This routine is typically called by the MUX when it has received a call to
muxDevUnload( ) for a specific network device. Before unloading the driver,
every network service bound to that device is issued a shutdown message by
calling the stackShutdownRtn( ) routine registered for that service.
Within this routine, the network service must call muxUnbind( ) to release itself
from the device, and it should bring itself to an orderly halt.
The stackShutdownRtn( ) prototype is:
STATUS stackShutdownRtn
(
void * netCallbackId /* the handle/ID installed at bind time */
)

stackRcvRtn( )

The MUX forwards packets received by the driver to the protocol layer by using
the stackRcvRtn( ) callback that was installed with muxTkBind( ). This routine
receives:
■ a pointer to an mBlk chain containing the incoming packet
■ the callback ID specific to the binding instance of the service/driver pair
■ a network service type
■ a pointer to additional data, the format of which, and the need for which,
depends on the requirements of the driver
The stackRcvRtn( ) prototype is:
BOOL stackRcvRtn
( 22
void * netCallbackId, /* the handle/ID installed at bind time */
long type, /* network service type */
M_BLK_ID pNetBuf, /* network service datagram */
void * pSpareData /* pointer to optional data from driver */
)

If a network protocol accepts the frame by returning TRUE, it must free the given
mBlk chain when processing is complete.

517
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

stackErrorRtn( )

Error conditions encountered by a driver are passed to the network service when
the MUX calls stackErrorRtn( ). It is up to the network service to take the necessary
action upon receiving the error.
This routine takes two arguments: the callback identifier supplied to the service at
bind-time, and a pointer to an END_ERR structure that describes the error (see
B.3.2 END_ERR, p.594).
The stackErrorRtn( ) prototype is:
void stackErrorRtn
(
void * netCallbackId, /* the handle/ID installed at bind time */
END_ERR * pError /* pointer to structure containing error */
)

stackRestartRtn( )

This routine is called by the MUX to restart network services that had previously
stopped, perhaps because muxTkSend( ) had returned an error indicating that the
network service should wait before transmitting more packets.
When the device has determined that it has enough resources to resume
transmission, it will indicate this to the MUX, which will then call
stackRestartRtn( ).
This routine takes a single argument: the identifier specific to the service/driver
pair that was supplied at bind-time.
The stackRestartRtn( ) prototype is:
STATUS stackRestartRtn
(
void * netCallbackId /* the handle/ID installed at bind time */
)

22.3.2 Service Routines Registered Using muxBind( )

These routine prototypes are included in this chapter to help people maintaining
network services that were designed to work with muxBind( ), which predated the
NPT. If you are designing a new network service, implement the routines
associated with muxTkBind( ).

518
22 Integrating a New Network Service
22.3 Interfacing with the MUX

stackENDShutdownRtn( )

This routine is typically called by the MUX when it has received a call to
muxDevUnload( ) for the specified network interface. Before unloading the END,
every network service bound to that END’s device is issued a shutdown message
by calling the stackENDShutdownRtn( ) routine registered for the interface at bind
time.
Within this routine, the network service must call muxUnbind( ) to release itself
from the device, and it should bring itself to an orderly halt.
The stackENDShutdownRtn( ) prototype is:
STATUS stackENDShutdownRtn
(
void * pEND, /* END_OBJ from the driver’s load routine */
void * pSpare /* defined on a per-service basis */
)

stackENDRcvRtn( )

The MUX forwards packets received by the END to the protocol layer by using the
stackENDRcvRtn( ) callback that is installed with muxBind( ). The pNetBuff
contains the entire driver-level frame, and pLinkHdr contains information about
offsets to the network payload in the frame.
The stackENDRcvRtn( ) prototype is:
BOOL stackENDRcvRtn
(
void * pCookie, /* returned by muxBind() */
long type, /* from RFC 1700, or user-defined */
M_BLK_ID pNetBuff, /* packet with link-level info */
LL_HDR_INFO * pLinkHdr, /* link-level header info structure */
void * pCallbackId /* registered by the network svc with MUX */
)

If a network protocol accepts the frame by returning TRUE, it must free the given
mBlk chain when processing is complete.
22
stackENDErrorRtn( )

Error conditions encountered by an END are passed to the network service when
the MUX calls stackENDErrorRtn( ). It is up to the network service to take the
necessary action upon receiving the error.
This routine takes three arguments: the callback identifier supplied to the service
at bind-time, a pointer to an END_ERR structure, and the spare data, if any, defined
for the service during the bind phase.

519
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The stackENDErrorRtn( ) prototype is:


void stackENDErrorRtn
(
void * pEND, /* END_OBJ passed to the MUX by the driver */
END_ERR * pError, /* holds error information */
void * pSpare /* defined on a per-service basis */
)

stackENDRestartRtn( )

This routine is called by the MUX to restart network services that had previously
stopped, perhaps because muxTkSend( ) had returned an error indicating that the
network service should wait before transmitting more packets.
When the device has determined that it has enough resources to resume
transmission, it will indicate this to the MUX, which will then call
stackENDRestartRtn( ).
This routine takes a single argument: the identifier specific to the service/driver
pair that was supplied at bind-time.
The stackENDRestartRtn( ) prototype is:
STATUS stackENDRestartRtn
(
void * pEND, /* END_OBJ passed to the MUX by the driver */
void * pSpare, /* defined on a per-service basis */
)

22.4 Adding a Socket Interface to Your Service


One way to give applications easy access to your network service is to add socket
support to the service. In order to make it easier for you to write a network service
that includes sockets support, the Wind River Network Stack includes a standard
socket interface.
With the standard socket interface, you can add new socket back ends to access the
network stack through your protocol layer implementation. This allows
developers who are already familiar with the standard socket API to more easily
use your service.

520
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

The standard socket interface is designed so that socket back ends for multiple
protocol layer implementations can be used simultaneously. A layered
architecture makes this possible. The Wind River standard socket interface is a
layer above your back end socket layer, as shown in Figure 22-1.
This chapter introduces the process of implementing a socket back end.

Figure 22-1 The Standard Socket Interface

Application Application Application

An application makes
standard socket calls.

Wind River Standard Socket Interface

You must register The interface knows which


your socket back back end to use.
end.

Wind River BSD


Your Socket Back End Socket Back End

TCP UDP ...


Your Network Service
IP

MUX

22

22.4.1 Process Overview

Socket calls made by an application are directed to the correct underlying socket
back end based on the domain parameter that is passed to the socket( ) call when
the application creates the socket. If this parameter matches the domainReal
parameter that you use when you add your new socket back end with the
sockLibAdd( ) routine, the socket calls are directed to your back end.

521
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

When you register your socket back end, you give the system a table that is filled
with references to socket routines that you have created to support your
implementation (see The Socket Functional Interface, p.522). The system is then able
to support standard socket calls that are made using your back end.

22.4.2 Implementing a Socket Back End

To provide a socket back end requires that you implement socket functionality for
your service and that you make the system aware of this new sockets
implementation. The following sections show how this is done.

The Socket Functional Interface

The socket functional interface is the set of implementations of standard socket


routines that are supported by a particular socket back end. There are two steps
involved in creating a socket functional interface, both of which must be
completed before the network is initialized.
The first step in creating a socket functional interface is to create a unique constant
identifying the back end (for example, the BSD-specific INET back end is identified
by the constant AF_INET_BSD). Add this constant to the list found in
installDir/vxworks-6.n/target/h/wrn/coreip/sys/socket.h.
Then, create an initialization routine that returns a reference to a SOCK_FUNC table
filled with references to all of the routines that your socket back end will support,
and call sockLibAdd( ) to have this routine invoked by the system. (For details
about this initialization routine, see usrSockLibInit( ), p.525).

NOTE: You need not support all possible socket routines. A user application
calling a non-supported routine in your socket back end (indicated by a NULL
pointer in the SOCK_FUNC table) returns ENOTSUP to the calling application.

Populating the SOCK_FUNC Table

The SOCK_FUNC table is a structure containing references to implementations of


routines, such as bind( ), recvfrom( ), and setsockopt( ), that are common to all
sockets (see 22.4.3 Implementing Socket Routines, p.524). A new network service that
wants to be socket-accessible should implement service-specific versions of as
many of these routines as it intends to support. To support the registration of these
routines, the service should set up its usrSockLibInit( ) routine to return a
SOCK_FUNC table that is populated with references to these routines.

522
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

Adding the Socket Library

Use the sockLibAdd( ) routine to add new socket functionality to the system’s list
of socket implementations. As input, this routine expects a reference to the
usrSockLibInit( ) routine and the domain and service for which this socket
implementation is to be registered.

The sockLibAdd( ) Routine

Use the sockLibAdd( ) routine to make available a specific implementation of


sockets for a particular domain. This routine takes three parameters:
sockLibInitRtn
The parameter refers to a socket library initialization routine that is invoked
when sockLibAdd( ) is called (for details about this routine, see
usrSockLibInit( ), p.525). This routine, among other things, passes the table of
socket routine implementations to the system.
domainMap
This parameter is ignored.
domainReal
This parameter specifies the address family value (such as AF_INET) for which
to use the back end being added. It is an error to have more than one back end
specify the same domainReal value.
The following is an example of how sockLibAdd( ) might be called to add the BSD
sockets back end:
sockLibAdd ((FUNCPTR) bsdSockLibInit, AF_INET_BSD, AF_INET);

The sockLibAdd( ) routine is defined as follows:


STATUS sockLibAdd
(
FUNCPTR sockLibInitRtn, /* back end's initialization routine */
int domainMap, /* AF_FOO_BAR, identifying # of back end */ 22
int domainReal, /* AF_FOO, identifying # of domain */
)

The routine returns OK, or ERROR if the socket back end could not be added.

523
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

22.4.3 Implementing Socket Routines

This subsection provides implementation recommendations of the routines


referenced in a SOCK_FUNC table followed by implementation recommendations
for the routines referenced in an iosDrvInstall( ) call.

Implementation Recommendations a SOCK_FUNC Table

This subsection provides implementation details for the routines you must supply
in a SOCK_FUNC structure:
typedef struct sockFunc /* SOCK_FUNC */
{
FUNCPTR libInitRtn; /* sockLibInit() */
FUNCPTR acceptRtn; /* accept() */
FUNCPTR bindRtn; /* bind() */
FUNCPTR connectRtn; /* connect() */
FUNCPTR connectWithTimeoutRtn; /* connectWithTimeout() */
FUNCPTR getpeernameRtn; /* getpeername() */
FUNCPTR getsocknameRtn; /* getsockname() */
FUNCPTR listenRtn; /* listen() */
FUNCPTR recvRtn; /* recv() */
FUNCPTR recvfromRtn; /* recvfrom() */
FUNCPTR recvmsgRtn; /* recvmsg() */
FUNCPTR sendRtn; /* send() */
FUNCPTR sendtoRtn; /* sendto() */
FUNCPTR sendmsgRtn; /* sendmsg() */
FUNCPTR shutdownRtn; /* shutdown() */
FUNCPTR socketRtn; /* socket() */
FUNCPTR getsockoptRtn; /* getsockopt() */
FUNCPTR setsockoptRtn; /* setsockopt() */
FUNCPTR zbufRtn; /* ZBUF support */

/* The following IO-system handlers are called via wrappers */


/* in sockLib.c. */

FUNCPTR closeRtn; /* close */


FUNCPTR readRtn; /* read() */
FUNCPTR writeRtn; /* write() */
FUNCPTR ioctlRtn; /* ioctl() */
} SOCK_FUNC;

All socket back-ends must provide non-null function pointers for closeRtn,
readRtn, writeRtn, and ioctlRtn. If a back end does not want to support read,
write, and ioctl, it can return ERROR from these routines. Support for close is
required. The entry point descriptions below are in the same order as the structure
members listed above.

524
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

usrSockLibInit( )
The usrSockLibInit( ) routine should install the socket back end as a driver within
the Wind River Network Stack I/O system by calling iosDrvInstall( ), and then
should return a pointer to a SOCK_FUNC structure.
The iosDrvInstall( ) routine takes pointers to seven socket routines, four of which
must be supported by a socket back end: usrSockClose( ), usrSockRead( ),
usrSockWrite( ) and usrSockIoctl( )2. The iosDrvInstall( ) returns a driver
number, which should be stored by the socket back end.
Your usrSockLibInit( ) routine, which should be declared public, can be based on
the following skeleton:
SOCK_FUNC * usrSockLibInit (void)
{
/* install driver for socket */
int driverNum = iosDrvInstall( (FUNCPTR) NULL, (FUNCPTR) NULL,
(FUNCPTR) NULL, (FUNCPTR) usrSockClose,
(FUNCPTR) usrSockRead, (FUNCPTR) usrSockWrite),
(FUNCPTR) usrSockIoctl) );
if( driverNum == ERROR ) return( (SOCK_FUNC *) NULL );
/* Store driverNum somewhere convnient for future reference */
/* Initialize SOCK_FUNC table */
SOCK_FUNC * usrSockFuncs = (SOCK_FUNC *) malloc(sizeof(SOCK_FUNC));
if( !usrSockFuncs )
{
errno = ENOMEM;
return( (SOCK_FUNC *) NULL );
}
usrSockFuncs->libInitRtn = (FUNCPTR) usrSockLibInit;
usrSockFuncs->acceptRtn = (FUNCPTR) usrSockAccept;
/* and so forth... */
usrSockFuncs->setsockoptRtn = (FUNCPTR) usrSockSetSockOpt;
usrSockFuncs->zbufRtn = (FUNCPTR) usrSockZbufRtn;
usrSockFuncs->closeRtn = (FUNCPTR) usrSockCloseRtn;
return (usrSockFuncs);
}

usrSockAccept( )
22
This routine accepts a connection on a socket and returns a file descriptor
representing the new socket created for the connection. Typically for this routine
to succeed, the socket represented by fd must have been previously bound to an
address with usrSockBind( ) and enabled for connections by a call to
usrSockListen( ). When usrSockAccept( ) is called, addr should be an available
buffer, and addrlen should indicate the size of the buffer.

2. The others may be skipped as NULL pointers. For more information on these essential
routines, see Socket Routines Passed to iosDrvInstall( ), p.534.

525
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The usrSockAccept( ) routine will block the caller until a connection is present,
unless the socket has been explicitly marked as non-blocking.
The usrSockAccept( ) routine is of the form:
int usrSockAccept
(
struct socket ** pSo, /* pointer to pointer of parent socket */
struct sockaddr * addr, /* peer address */
int * addrlen /* peer address length */
)

This routine returns a file descriptor representing a new socket with the same
properties as the one represented by fd (or ERROR if the accept fails). In addition,
on a successful return, addr should be filled with the address of the machine
making the connection, and addrlen should be set to the length of that address.

usrSockBind( )

This routine associates a network address (referred to by name) with a specified


socket so that other processes can connect or send to it.
The usrSockBind( ) routine is of the form:
STATUS usrSockBind
(
struct socket * so, /* pointer to socket */
struct sockaddr * name, /* name to be bound */
int namelen /* length of name */
)

This routine returns OK, or ERROR if the bind fails.

usrSockConnect( )

This routine initiates a connection between a socket, fd, and another socket, which
is specified by name.
The usrSockConnect( ) routine is of the form:
STATUS usrSockConnect
(
struct socket * so, /* socket pointer */
struct sockaddr * name, /* addr of socket to connect */
int namelen /* length of name, in bytes */
)

This routine returns OK, or ERROR if the connection fails.

526
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

usrSockConnectWithTimeout( )

This routine tries to initiate a connection between socket, fd, and the socket
specified by name, for a duration specified by timeout, reporting an error if it cannot
do so in the time required. If timeout is NULL, this routine should act exactly like
usrSockConnect( ).
The usrSockConnectWithTimeout( ) routine is of the form:
STATUS usrSockConnectWithTimeout
(
struct socket * pSo, /* socket pointer */
struct sockaddr *adrs, /* addr of the socket to connect */
int adrsLen, /* length of the socket, in bytes */
struct timeval *timeVal /* time-out value */
)

This routine returns OK, or ERROR if the connection is not made in time.

usrSockGetpeername( )

This routine gets the name of the peer connected to the socket fd, placing this name
in the sockaddr structure of length namelen that was passed in.
The usrSockGetpeername( ) routine is of the form:
STATUS usrSockGetpeername
(
struct socket *so, /* socket descriptor */
struct sockaddr *name, /* where to put name */
int *namelen /* space available in name, later */
/* filled in with actual name size */
)

This routine should place the name of the peer in name and sets namelen to the size
of this name in bytes, then return OK, or ERROR if a name could not be retrieved
for the specified socket.

usrSockGetsockname( )

This routine gets the current name for the socket fd, placing this name in the 22
available sockaddr structure of size namelen that was passed in.
The usrSockGetsockname( ) routine is of the form:
STATUS usrSockGetsockname
(
struct socket *so, /* socket descriptor */
struct sockaddr *name, /* where to return name */
int *namelen /* space available in name, later */
/* filled in with actual name size */
)

527
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This routine places the name of the socket in name and set namelen to the size of this
name in bytes, then returns OK, or ERROR if a name could not be retrieved for the
specified socket.

usrSockListen( )

This routine enables connections to a socket. The backlog parameter specifies the
maximum number of unaccepted connections that can be pending at any given
time. After enabling connections with usrSockListen( ), connections are actually
accepted by usrSockAccept( ).
The usrSockListen( ) routine is of the form:
STATUS usrSockListen
(
struct socket * so, /* socket pointer */
int backlog /* max number of unaccepted pending connections */
)

This routine returns OK, or ERROR if the listen request fails.

usrSockRecv( )

This routine receives data from a connection-based (stream) socket. How the flags
parameter should be set depends on the nature of the sockets involved and the
requirements of the connection. This will differ for different socket and service
implementations.
The usrSockRecv( ) routine is of the form:
int usrSockRecv
(
struct socket *so, /* socket to receive data from */
char *buf, /* buffer to write data to */
int bufLen, /* length of buffer */
int flags /* flags to underlying protocols */
)

NOTE: If the MSG_MBUF flag is set in the flags parameter, this means that a
zero-copy buffer (zbuf) is being received. A non-NULL mbuf ID is passed to the
back-end (that is, an mbuf ID structure is created). The mbuf ID will not point to
data.

The usrSockRecv( ) routine should set buf to point to the mbuf chain holding the
incoming data.
This routine returns the number of bytes received, or ERROR if the receive fails.

528
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

usrSockRecvFrom( )

This routine receives data from a datagram socket, regardless of whether it is


connected. When this routine is called, from will either be NULL or will be an
available buffer of size pFromLen designed to hold the address from which the data
is coming. How the flags parameter should be set depends on the nature of the
sockets involved and the requirements of the connection. This will differ for
different socket and service implementations.
The usrSockRecvFrom( ) routine is of the form:
int usrSockRecvFrom
(
struct socket *so, /* socket to receive from */
char *buf, /* pointer to data buffer */
int bufLen, /* length of buffer */
int flags, /* flags to underlying protocols */
struct sockaddr *from, /* where to copy sender's addr */
int *pFromLen /* value/result length of <from> */
)

NOTE: If the MSG_MBUF flag is set in the flags parameter, this means that a
zero-copy buffer (zbuf) is being received. In this case, the buf parameter is a pointer
to a NULL mbuf pointer and not the char * specified in the parameter list. In other
words, *buf = (struct mbuf *) NULL. The usrSockRecvFrom( ) routine should set buf
to point to the mbuf chain holding the incoming data.

If from is not NULL, the address of the sending socket is copied into it, and
pFromLen is set to the length of this address. This routine returns the number of
bytes received, or ERROR if the receive fails.

usrSockRecvMsg( )

This routine receives a message from a datagram socket. It may be used in place of
usrSockRecvFrom( ) to decrease the overhead of breaking down the
message-header structure in each message. How the flags parameter should be set
depends on the nature of the sockets involved and the requirements of the 22
connection. This will differ for different socket and service implementations.
The usrSockRecvMsg( ) routine is of the form:
int usrSockRecvMsg
(
struct socket * so, /* socket to receive from */
struct msghdr * pMsgHdr, /* the message header */
int flags /* flags describing nature of the data */
)

This routine returns the number of bytes received, or ERROR if the receive fails.

529
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

usrSockSend( )

This routine transmits data from the socket fd to a previously established


connection-based (stream) socket. How the flags parameter should be set depends
on the nature of the sockets involved and the requirements of the connection. This
will differ for different socket and service implementations.
The usrSockSend( ) routine is of the form:
int usrSockSend
(
struct socket * so, /* socket to send to */
char * buf, /* buffer containing data to be sent */
int bufLen, /* length of the buffer */
int flags /* flags describing the nature of the data */
)

This routine returns the number of bytes sent, or ERROR if the send fails.

usrSockSendto( )

This routine transmits data from the socket specified by fd to the datagram socket
specified by to. How the flags parameter should be set depends on the nature of the
sockets involved and the requirements of the connection. This will differ for
different socket and service implementations.
The usrSockSendto( ) routine is of the form:
int usrSockSendto
(
struct socket * so, /* socket to send to */
caddr_t buf, /* buffer with message to be sent */
int bufLen, /* length of this buffer */
int flags, /* flags describing nature of the data */
struct sockaddr * to, /* recipient's address */
int tolen /* length of the to structure */
)

This routine returns the number of bytes sent, or ERROR if the send fails.

usrSockSendMsg( )

This routine transmits a message to a datagram socket specified by fd. It may be


used in place of usrSockSendto( ) to decrease the overhead of reconstructing the
message header structure for each message. How the flags parameter should be set
depends on the nature of the sockets involved and the requirements of the
connection. This will differ for different socket and service implementations.

530
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

The usrSockSendMsg( ) routine is of the form:


int usrSockSendMsg
(
struct socket * so, /* socket to send to */
struct msghdr * pMsgHdr, /* message header */
int flags /* flags to underlying protocols */
)

This routine returns the number of bytes sent, or ERROR if the send fails.

usrSockShutdown( )

This routine shuts down all, or part, of the connection-based socket fd. The how
value allows for some control over how this shutdown takes place if sends and
receives are still pending.
The usrSockShutdown( ) routine is of the form:
STATUS usrSockShutdown
(
struct socket * so, /* socket to shut down */
int how /* directs how shutdown proceeds when activity is pending */
)

This routine returns OK, or ERROR if the specified socket was invalid or could not
be shut down.

usrSocket( )

When you call socket( ), the standard socket interface searches for a back end that
corresponds to the domain parameter passed to socket( ). This domain parameter
must be the actual protocol family value. That is, it must match the domainReal
parameter passed to the sockLibAdd( ) that registered the socket back end for the
specified family.
If a back end is found for the domain, this triggers a call to the usrSocket( ) routine
from the SOCK_FUNC structure that was registered for that domain. In some
previous stack releases, domain could have been the domainMap value passed to
sockLibAdd( ), which might have differed from domainReal. In the current 22
implementation, sockLibAdd( ) ignores its domainMap parameter.
The usrSocket( ) routine should create a socket structure and then generate a new
file descriptor representing the socket by calling iosFdNew( ) with the address of
the new socket structure. Other back end routines will receive this file descriptor
as a reference, and will use it to retrieve the associated socket structure by calling
iosFdValue( ) with the file descriptor as an argument.

531
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The usrSocket( ) routine is of the form:


int usrSocket
(
int domain, /* socket domain or address family number */
int type, /* socket's nature, e.g. SOCK_DGRAM */
int protocol /* the protocol variety of the socket */
)

The domain argument refers to the socket domain or address family the socket
belongs to (a particular back end may potentially be invoked for more than one
domain). The type argument can be used to further define the nature of the socket
(examples of types in the AF_INET domain include SOCK_STREAM, SOCK_RAW
and SOCK_DGRAM). The protocol argument refers to the protocol variety of the
socket (in the AF_INET_BSD back end, an example of a protocol variety is
IPPROTO_TCP).
The usrSocket( ) routine returns the file descriptor that was generated for the
socket, or ERROR if it was unable to open a socket.

usrGetSockOpt( )

This routine retrieves socket option values3 associated with a specified socket. To
find options set at the socket level, level is set to SOL_SOCKET. To find options set
for a particular service, level is set to the identifying number of that service. The
optval parameter points to an available buffer of size optlen. The buffer itself,
although passed in as a char *, is treated as a pointer to whatever data type or
structure is appropriate to the option being referenced.
The usrGetSockOpt( ) routine is of the form:
STATUS usrGetSockOpt
(
struct socket *so, /* socket */
int level, /* protocol level for options */
int optname, /* name of option */
char *optval, /* where to put option */
int *optlen /* where to put option length */
)

This routine fills optval with the setting of the specified option, and sets optlen to
the actual size of this value. The routine returns OK, or ERROR if it was unable to
retrieve a value for this option given these parameters.

3. For instance, in TCP, socket options include SO_KEEPALIVE, SO_LINGER and


TCP_NODELAY.

532
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

usrSetSockOpt( )

This routine sets the options associated with a socket4. To manipulate options at
the socket level, level is set to SOL_SOCKET. Otherwise, level is set to the service
number of the service for which the option is being set.
The usrSetSockOpt( ) routine is of the form:
STATUS usrSetSockOpt
(
struct socket * so, /* target socket */
int level, /* protocol level of option */
int optname, /* name of option being set */
char * optval, /* value the option is being set to */
int optlen /* length of the value field */
)

This routine returns OK, or ERROR if the request to set the socket option for the
specified socket fails.

usrSockZbufRtn( )

This routine returns TRUE if the back end supports the zero-copy interface (zbufs),
otherwise it returns FALSE. The usrSockZbufRtn( ) routine is of the form:
STATUS usrSockZbufRtn( )

usrSockClose( )

This routine is called by the I/O system to close a socket. It is also passed to the
iosDrvInstall( ) call in the initialization routine and is described below.

usrSockReadRtn( )

This routine is called by the I/O system to read a socket. It is also passed to the
iosDrvInstall( ) call in the initialization routine and is described below.

usrSockWriteRtn( )

This routine is called by the I/O system to write to a socket. It is also passed to the 22
iosDrvInstall( ) call in the initialization routine and is described below.

usrSockIoctlRtn( )

This routine, described below, is called by the I/O system to perform an ioctl call
on a socket and is passed to the iosDrvInstall( ) call in the initialization routine.

4. For instance, in UDP, socket options include SO_BROADCAST, IP_ADD_MEMBERSHIP


and IP_MULTICAST_IF.

533
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Socket Routines Passed to iosDrvInstall( )

An iosDrvInstall( ) call expects pointers to routines to handle:



closing the socket

reading the socket

writing to the socket

I/O control for the socket
In the routines below, the socket structure parameter corresponds to whatever data
structure describes the socket object that was returned from iosFdValue( ). This
might be a struct socket, or it may be some other structure.

usrSockClose( )

The usrSockClose( ) routine is called by the I/O system to close a socket and is of
the form:
int usrSockClose
(
[socket structure] * so /* socket being closed */
)

This routine returns 0 on success, or -1 on failure.

usrSockRead( )

The usrSockRead( ) routine is of the form:


int usrSockRead
(
[socket structure] * so, /* socket being read from */
char * buf, /* buffer to contain incoming data */
int bufLen /* length of this buffer */
)

This routine returns the number of bytes read, or -1 if the read fails.

usrSockWrite( )

The usrSockWrite( ) routine is of the form:


int usrSockWrite
(
[socket structure] * so, /* socket being written to */
char * buf, /* buffer containing outgoing data */
int bufLen /* length of this buffer */
)

This routine returns the number of bytes written, or -1 if the write fails.

534
22 Integrating a New Network Service
22.4 Adding a Socket Interface to Your Service

usrSockIoctl( )

The usrSockIoctl( ) routine is of the form:


int usrSockIoctl
(
[socket structure] * so, /* file descriptor representing the socket */
int function, /* the ioctl function being called */
int arg /* the argument to this ioctl function */
)

This routine returns a positive number whose value depends on the ioctl routine
being invoked, or -1 in the case of an error.

22

535
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

536
23
Working with the
802.1Q VLAN Tag

23.1 Introduction 537


23.2 Adding VLAN Support 538
23.3 Configuring VxWorks for 802.1Q VLAN Tagging 539
23.4 About the 802.1Q VLAN Tag Header 540
23.5 MUX Extensions for Layer 2 VLAN Support 541
23.6 Current MUX-L2 Limitations 547
23.7 VLAN Management 548
23.8 Using the MUX-L2 Show Routines 558
23.9 Using the Deprecated VLAN Tag Library 560

23.1 Introduction
This chapter tells you how to use the implementation of 802.1Q VLAN tagging for
VxWorks. It assumes that you are familiar with the principles and operations of
Layer 2 network services.

NOTE: 802.1Q VLAN tagging is available in the Wind River Platforms builds of the
network stack. The Wind River General Purpose Platform, VxWorks Edition, does
not support 802.1Q VLAN tagging.

537
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Previously, support for 802.1Q VLAN tagging was supplied by vlanTagLib. In the
current stack, the 802.1Q VLAN support is integrated with the network stack as
MUX-L2 functionality. You can access this functionality by any of the following
methods:

through the muxL2name( ) routines

through extensions to the socket interface
■ through a new pseudo interface that you can use to manage the VLAN as a
subnet
You can also access this functionality through vlanTagLib, but keep in mind that
vlanTagLib is now deprecated.

NOTE: Although the MUX provides functionality for managing packets tagged
with an 802.1Q tag header, it does not implement the IEEE 802.1P/Q protocols.

23.2 Adding VLAN Support


This section describes how to build the source code for VLAN support and which
components to add to your VxWorks image.

23.2.1 Building VxWorks with VLAN Support

To assure that the components required for VLAN support are available when
configuring an image, you need to build the network stack code using the
following options:

-DSOCKET_VLAN builds the socket-based VLAN support into the socket
backend code.

-DSUBNET_VLAN builds in support for the FreeBSD-style VLAN
pseudo-interface for subnet-based VLAN support.
For information on building the network stack, see your Wind River Platforms
Getting Started.

538
23 Working with the 802.1Q VLAN Tag
23.3 Configuring VxWorks for 802.1Q VLAN Tagging

23.3 Configuring VxWorks for 802.1Q VLAN Tagging


The Wind River Network Stack supports the following 802.1Q VLAN
configuration components:

MUX Layer 2 Support

Subnet-Based VLAN

L2Config
These components are all listed under the
Network Components > Layer2_Network Components folder in Workbench.

NOTE: For information on the INCLUDE_VLAN_TAG component, see 23.9 Using


the Deprecated VLAN Tag Library, p.560.

MUX Layer 2 Support

The INCLUDE_MUX_L2 component pulls in the MUX network interface library for
layer 2. Including this component initializes the MUX-L2 infrastructure for VLAN
support.
This component is automatically included when the INCLUDE_SUBNET_VLAN
component is included, and it requires the following configuration components:
■ INCLUDE_END

INCLUDE_ETHERNET

This component contains the following configuration parameters:

MUX_L2_MAX_VLANS_CFG

Synopsis: Specifies the maximum number of 802.1Q VLANs supported on


the target.
Default: 16

MUX_L2_NUM_PORTS_CFG 23

Synopsis: Specifies the maximum number of physical ports available to the


target.
Default: 16

539
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Subnet-Based VLAN

The INCLUDE_SUBNET_VLAN component provides support for Layer 2


subnet-based VLANs. Including this component initializes the FreeBSD-style
VLAN pseudo-interface for subnet-based VLAN support.
This component requires the following configuration components:

INCLUDE_MUX_L2
■ INCLUDE_IFCLONE

L2Config

The INCLUDE_L2CONFIG component provides support for the layer 2


configuration utility. Including this component initializes the L2 command-line
configuration utility. This component requires theINCLUDE_MUX_L2 component.

23.4 About the 802.1Q VLAN Tag Header


The current Wind River VLAN implementation supports the following three
frame types:
■ Untagged frames – frames that do not carry any identification of the VLAN to
which it belongs.
■ Priority-tagged frames – frames that include a tag header carrying explicit user
priority information but not identifying the frames as belonging to a specific
VLAN.

VLAN-tagged frames – frames that include an explicit identification of the
VLAN to which it belongs.
The VLAN tag header is as shown in Figure 23-1.
The 802.1Q tag is a four-byte field added to the Ethernet header after the six-byte
Source Address field and before the two-byte length/type field. A tagged frame is
indicated by the Type field equal to the VLAN Identifier Protocol (0x8100). The
presence of this field means the next two bytes contain Tag Control Information.

540
23 Working with the 802.1Q VLAN Tag
23.5 MUX Extensions for Layer 2 VLAN Support

Figure 23-1 VLAN Tag Header Format on Ethernet

Destination Source VLAN Length/


Address Address Tag Type Data CRC

6 bytes 6 bytes 4 bytes 2 bytes 42 to 1500 bytes 4 bytes

TPID TCI
4 bytes (Tag Control
Tag Protocol
VLAN Tag Information)
ID

2 bytes User Priority CFI VLAN ID


TCI (3 bits) (1 bit) (12 bits)

The two-byte Tag Control Information is broken into a 3-bit priority (0-7) value, a
Canonical Format Indicator (CFI) field (0 for Ethernet), and a 12-bit VLAN
Identifier (VID). Although the 12-bit VID field can take any value from 0 to 4095,
the only VID values you may use (in management operations) range from 1 to
4094. The value of all ones (0xFFF) is reserved and currently unused. The value of
all zeros (0x000) indicates a priority-tagged frame and that no VID is present in the
frame.

23.5 MUX Extensions for Layer 2 VLAN Support 23

This section describes functionality you can use to programatically control the
MUX-L2 VLAN support functionality. For information on doing this from the
command line, see 23.7.1 MUX-L2 VLAN Management, p.548.

541
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

23.5.1 Overview of MUX-L2 Supported Functionality

The MUX-L2 extensions provide the fundamental infrastructure needed to


manage the VLAN membership for a VxWorks target. These extensions support
the following 802.1Q characteristics:

VLAN classification of untagged, priority-tagged, or VLAN-tagged ingress
frames.
■ Port-based VLAN classification as the default ingress rule. That is, all
untagged and priority-tagged frames received by a port are classified as
belonging to the VLAN whose VID is associated with that port.
■ VLAN-tagged, priority tagged, or untagged frames on egress.
■ Multiple VLAN memberships for a port. That is, a port can be a member of
multiple VLANs.
■ Ingress Filter and Ingress Acceptable Frame Type configuration on a per-port
basis.
■ Lets you send untagged frames for some VLANs and VLAN-tagged frames for
others on a per-port basis.
■ Assigns all VLAN-enabled ports to the default PVID of 1. The PVID value of a
port is configurable.
You can access and control this functionality through the muxL2name( ) routines,
through a socket interface, or a newly ported VLAN pseudo interface.

23.5.2 Enabling VLAN Support for a Port

For an END device loaded to MUX, you can call the muxL2PortAttach( ) routine
to enable VLAN support for the port.

NOTE: The muxL2PortAttach( ) routine assumes an Ethernet device. If you are


using a non-Ethernet device, use muxL2PortAltAttach( ). More information on
this routine is provided in 23.5.3 Attaching Non-Ethernet Devices, p.544.

542
23 Working with the 802.1Q VLAN Tag
23.5 MUX Extensions for Layer 2 VLAN Support

Internally, the muxL2PortAttach( ) prepares the port for VLAN support as


follows:

Joins the port to the default VLAN with a VID of 1, as per 802.1Q requirement.
It also configures the port to transmit untagged frames on the default VLAN.
The egress tagging state for the default Port VLAN ID (PVID) can be changed
by calling muxL2Ioctl( ) with the MUXL2IOCSPORTVLAN control command.
■ Initializes the port-specific attributes with default as follows:
– Default Port User priority: 0
– Ingress Acceptable Frame Filter Type: admits all frame types
– Ingress Filter: False
■ Queries the hardware for its VLAN capabilities. The driver must indicate that
it supports hardware VLAN tagging by setting IFCAP_VLAN_HWTAGGING
in if_capabilities. Drivers for hardware that can handle larger MTUs that might
include a software-appended VLAN header without lowering the normal
MTU should set IFCAP_VLAN_MTU in if_capabilities. This notifies the
MUX-L2 that it can leave the MTU on the for the port at the normal setting. If
the IFCAP_VLAN_MTU flag is not set and software VLAN-tagging is required,
the MUX-L2 decreases the hardware MTU by 4-bytes.
■ Determines which type of Ethernet address format the device can support
(Ethernet Type 2 encapsulation or 802.3 style length encapsulation). The
information is required when the MUX-L2 assembles an Ethernet header for
the egress frame.
■ Saves the address of the original END driver's function table. The MUX-L2 will
restore the original driver's function table during muxL2PortDetach( ).
■ Replaces the driver's registered driverNamepacketDataGet( ) with
muxL2IngressClassify( ), and the driverNameformAddress( ) function pointer
with muxL2EgressClassify( ). For more information about MUX-L2 ingress
and egress frame processing, see 23.5.5 MUX-L2 Ingress Rules, p.544, and
23.5.6 MUX-L2 Egress Rules, p.546.

NOTE: As an alternative to muxL2PortAttach( ), you can call muxL2Ioctl( ) using 23


the MUXL2IOCSPORTATTACH control command.

543
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

23.5.3 Attaching Non-Ethernet Devices

The muxL2PortAltAttach( ) provides a mechanism to attach a non-Ethernet device


to MUX-L2. The muxL2PortAltAttach( ) routine has the following prototype:
STATUS muxL2PortAltAttach
(
char* pDevName, /* pointer to device name */
int unit, /* unit number for a single device */
BOOL updateNetFuncs, /* update driver's NET_FUNCS table or not */
M_BLK_ID (*formAddress)(), /* driver's address formation func */
STATUS (*packetDataGet)(), /* driver's packet data get func */
STATUS (*ingressVlanTagCheck)()
)

To use this routine, the caller must set the updateNetFuncs boolean to TRUE and
provide nameFormAddress( ) and namePacketDataGet( ) routines that can handle
the 802.1Q VLAN tag header. The formAddress( ) routine is expected to perform
the egress rules checking and build the appropriate link-level header with the
appropriate address format that may or may not include a VLAN Tag header.
The namepacketDataGet( ) routine must perform the 802.1Q Ingress VLAN
classification as described in the IEEE 802.1Q specification. Thus, it must extract
the packet data and copy the link-level header information from the received
frame.

23.5.4 Disabling VLAN Support for a Port

To disable VLAN support for a port, call muxL2PortDetach( ). The


muxL2PortDetach( ) routine detaches the port from the MUX-L2, removes the port
from all the VLAN memberships it has joined, and restores the original driver's
function table. If the port is removed from the MUX, the muxDevUnload( )
forcibly calls muxL2PortDetach( ) as well.

NOTE: As an alternative to muxL2PortDetach( ), you can call muxL2Ioctl( ) using


the MUXL2IOCSPORTDETACH control command.

23.5.5 MUX-L2 Ingress Rules

When a frame arrives on a port, the driver's interrupt service routine schedules the
frame processing work to tNetTask. The MUX receive routine would normally
schedule a call to the driver's namePacketDataGet( ) to separate the address
information and data in the frame.

544
23 Working with the 802.1Q VLAN Tag
23.5 MUX Extensions for Layer 2 VLAN Support

Figure 23-2 MUX-L2 Ingress Rules

From MUX
Receive Routine EtherType No LLC DSAP Yes
> 1500 802.2 = 0x42
Address
Ethernet Type 2 Format
Yes No
Address Format

Extract VLAN Yes Ethertype


ID & User
Found Tag = 0x8100
Priority.
Untagged
No

Yes Admit All No VLAN


VID = 0 Independent
Priority-tagged Frames
BPDU
?
No Yes

Port-Based
VLAN
VID = PVID

Ingress
No No
VID = 4095 Filter
Enabled
?
Yes Yes

Port is 23
member of Yes Fill in the link
VLAN header info.
?
No

Discard
Frame.

545
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

However, for a VLAN-enabled port, the MUX receive routine schedules a call to
muxL2IngressClassify( ) to filter the received frame according to its VLAN header
tag. Figure 23-2 shows how the ingress filter handles an incoming frame.

23.5.6 MUX-L2 Egress Rules

When the MUX needs to transmit a frame, it normally calls the driver's
nameFormAddress( ) routine to create and prepend a link-layer-appropriate frame
header to the mBlk chain containing outgoing data. However, for packets
transmitted over a VLAN-enabled port, some additional pre-processing is
required.

Figure 23-3 MUX-L2 Egress Rules

From Output Routine

Yes Send No Send No


Untagged Extract VID and
Priority Tagged
Frame? user priority.
Frame VLAN
? Tagged
Yes Frame

Yes Port-Based
VID = 0 VLAN
VID = PVID

No

Offload VLAN Yes Yes Port is


Tag Header HW Tagging member of
to hardware. ? VID
?
No No

Build Ethernet
Build a normal header with VLAN Discard
Ethernet header. Tag Header. Frame.

546
23 Working with the 802.1Q VLAN Tag
23.6 Current MUX-L2 Limitations

In addition, 802.1Q requires that a port transmits only VLAN-tagged frames or


untagged frames but never transmits using both formats for the same VLAN. To
support the egress tagging decision on a per-port per-VLAN basis, the MUX-L2
keeps track of the per-port egress tagging configuration for each VLAN.
To evaluate an outgoing frame in accordance with this information, the MUX calls
muxL2EgressClassify( ) to determine whether the outgoing frame should be
tagged or untagged, and then to build the link-layer header based on the tagging
decision. Figure 23-3 shows how the egress filter handles an outgoing frame.

23.5.7 Accessing the MUX L2 Control Routines

Use muxL2Ioctl( ) to access the MUX-L2 control functionality. These control


routines let you do things such as retrieve port information, set the ingress frame
filter type, and more. For more information, see the muxL2Ioctl( ) reference entry.

23.6 Current MUX-L2 Limitations


The current MUX-L2 implementation has the following known limitations:

There is no support for the automatic distribution of VLAN configuration
using the GARP VLAN Registration Protocol (GVRP). The MUX-L2 support
for VLAN is limited to those created statically.

The MUX-L2 does not implement the configuration and operation of the
address learning process described in the 802.1Q specification. Therefore, it is
not capable of broadcasting or multicasting frames to multiple ports belonging
to a VLAN.

Although the MUX-L2 allows the 802.1P User Priority to be specified with an
egress VLAN-tagged frame, it does not support user priority to traffic class 23
mapping described in the 802.1Q specification. It also does not provide any
mechanism to perform the ingress user priority regeneration as described in
the 802.1Q specification.

Although the MUX-L2 implements selected RFC 2674 static VLAN objects, the
VLAN configuration methodology is not compatible with the RFC 2674 MIB.
RFC 2674 VLAN management is VLAN centric and requires a port list bitmap
specifying the ports belonging to a VLAN. The VLAN management for the

547
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

MUX-L2 is port-centric and VLAN configuration is achieved on a per-port


basis.

The support for 802.1Q VLAN tagging is currently implemented for END
devices only. NPT-style driver support is not available at this time.

The MUX-L2 implementation is provided in the context of Ethernet as the
underlying data link technology. Because the fundamental VLAN operation
and behavior are independent of the underlying data link, the implementation
can be easily modified to adapt to a non-Ethernet environment. For more
information, see 23.5.3 Attaching Non-Ethernet Devices, p.544.
■ Wind River Learning Bridge is incompatible with the MUX-L2.

23.7 VLAN Management


The following subsections describe mechanisms you can use to manage a VLAN.

23.7.1 MUX-L2 VLAN Management, p.548

23.7.2 Socket-Based VLAN Management, p.550

23.7.3 Subnet-Based VLAN Management, p.553
When reading these sections, be aware that changes that occur at different layers
in the stack are not of equal priority. Thus, when you specify a user priority for
socket-based VLAN, a subnet-based VLAN cannot change it. Likewise be aware
that there are consequences to changing the VID.

23.7.1 MUX-L2 VLAN Management

Using the l2config utility, you can access the Layer 2 set routines supported by
muxL2Ioctl( ). The l2config utility does not provide access to the muxL2Ioctl( ) get
functionality, which, because of its use of structures, is more suited to
programmatic use. However, you can access much of the same information from
the command line using muxL2Show( ) or muxL2VlanShow( ), which are
described in their respective reference entries and in 23.8 Using the MUX-L2 Show
Routines, p.558.

548
23 Working with the 802.1Q VLAN Tag
23.7 VLAN Management

For port-oriented configuration needs, l2config supports the following:



Attach/detach a port to/from MUX-L2.

Set the default port VID (PVID).

Set the default user priority.

Set the acceptable ingress frame type.

Set the ingress frame filter.
For configuration needs involving both the port and a VLAN, l2config supports
the following:
■ Join a port to a VLAN.
■ Set the egress frame type for the VLAN.
■ Leave a VLAN that a port joined previously.
For more information, see the examples below and the reference entry for l2config.

Sample MUX-L2 Configuration

The following example attaches the fei1 port to MUX-L2:


-> l2config "vlandev fei1 attach"
value = 0 = 0x0

The following example enables the ingress frame filter for port fei1. It also sets the
fei1 ingress acceptable frame filter type to ADMIT_TAGGED_ONLY_FRAMES:
-> l2config "vlandev fei1 infilter on ingress admittag"
value = 0 = 0x0

The following example joins the fei1 port to the VLAN with VID 20 and configures
the egress frame type for the VLAN to transmit VLAN-tagged frames only:
-> l2config "vlandev fei1 join vid 20 egress tagged"
value = 0 = 0x0

The following example removes the fei1 port from VLAN 20, the VLAN to which
it was joined previously:
-> l2config "vlandev fei1 leave vid 20"
value = 0 = 0x0

The following example demonstrates the ability of l2config to allow multiple 23


command options to be specified at the same time. For example, the attach and join
commands above can be combined into one:
-> l2config "vlandev fei1 attach join vid 20 egress tagged"
value = 0 = 0x0

549
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

23.7.2 Socket-Based VLAN Management

Because the traditional socket API does not provide a mechanism that can carry all
the information relevant to VLAN configuration, Wind River has extended the
socket API to include a new socket option, SO_VLAN, and a new structure, sovlan.
By treating the VID and the user priority as socket-level configuration options, you
can use these extensions in the getsockopt( ) and setsockopt( ) calls and thus get
or set VLAN membership information.
The sovlan structure is defined as follows:
struct sovlan {
/*
* If so_onff is set, the vlan id and/or user priority will be copied
* to the socket structure and SO_VLAN so_option will be set. If so_onff
* is not set, the SO_VLAN so_option for the socket will be cleared.
*/
int vlan_onoff; /* on/off option */

/*
* The priority_tagged boolean must be set to true if application using
* socket-based vlan requires to egress 802.1P priority-tagged frame
* (i.e. the value of vid is zero). Defaults to false. If set to true,
* the value specified by the vid will be ignored.
*/

BOOL priority_tagged;

unsigned short vid; /* VLAN ID, valid vid: 1..4094 */


unsigned short upriority; /* User Priority, valid priority: 0..7 */
};

After a socket is created, an application can use setsockopt( ) to configure the VID
and/or user priority for the given socket. In order to transmit a VLAN-tagged or
priority-tagged frame, the port/interface that the socket bound to must have
already attached to the MUX-L2 as described previously. If transmitting a
VLAN-tagged frame, the transmitting port must also be a member of the VLAN
that the socket-based VLAN is configured for.

Setting User Priority for Transmitted Priority-tagged Frames

The following code fragment provides an example of how to use setsockopt( ) to


configure the user priority for the specified socket and to configure that socket to
transmit priority-tagged frames.
struct sovlan vl;

/* setup the vlan_onoff to indicate that the VID and or User Priority
* are valid */

vl.vlan_onoff = 1;

550
23 Working with the 802.1Q VLAN Tag
23.7 VLAN Management

/*
* Informs lower-layers (such as subnet-based VLAN and MUX-L2) that the
* information provided is for Priority-tagged frame and that lower-layers
* must not alter the VLAN control information for VID configuration
*/

vl.priority_tagged = TRUE;

/* VID is not applicable for Priority-tagged frame */

vl.vid = 0;

/* Configure the Priority-tagged frame for User Priority with value 7 */

vl.upriority = 7;
if ( setsockopt(s, SOL_SOCKET, SO_VLAN, (char *)&vl, sizeof(struct sovlan))
< 0)
printf("setsockopt SO_VLAN for socket %d failed\n", s);

Setting User Priority for Transmitted VLAN-tagged Frames

The following code fragment provides an example of how to use setsockopt( ) to


configure the user priority for the specified socket and to configure that socket to
transmit VLAN-tagged frames.
struct sovlan vl;

/* setup vlan_onoff to indicate that VID and/or User Priority * are valid */

vl.vlan_onoff = 1;

/*
* Informs lower-layers (such as Subnet-based VLAN and MUX-L2) that the
* information provided is for VLAN-tagged frame and that lower-layers should
* alter the VLAN control information for VID if the VID is not specified
*/

vl.priority_tagged = FALSE;

/*
* Specifies VID with value of 0 to allow lower-layers (such as Subnet-
* based VLAN or MUX-L2) to insert the appropriate VID to the VLAN
* control information for the outgoing VLAN-tagged frame. 23
*/

vl.vid = 0;

/* Configure the VLAN-tagged frame for User Priority with value 3 */


vl.upriority = 3;

if (setsockopt(s, SOL_SOCKET, SO_VLAN, (char *)&vl, sizeof(struct sovlan)) <


0)
printf("setsockopt SO_VLAN for socket %d failed\n", s);

551
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Clearing the VLAN Configuration for the Socket

Consider the following code fragment:


struct sovlan vl;

bzero ((char *)&vl, sizeof(struct sovlan);

/* reset all the VLAN control information for the socket */

vl.vlan_onoff = 0;

if ( setsockopt(s, SOL_SOCKET, SO_VLAN, (char *)&vl, sizeof(struct sovlan))


< 0)
printf("setsockopt SO_VLAN for socket %d failed\n", s);

Getting Configuration Information

The following code fragment provides an example of how to use getsockopt( ) to


retrieve the VLAN configuration for a specified socket.
struct sovlan vl;
int vsize = sizeof(struct sovlan);;

bzero ((char *)&vl, sizeof(struct sovlan));


if (getsockopt(s, SOL_SOCKET, SO_VLAN, (char *)&vl, &vsize) < 0)
printf("getsockopt SO_VLAN for socket %d failed\n", s);
if (vl.vlan_onoff == 0)
printf("No VLAN control info for socket %d\n", s);
else
{
if (vl.priority_tagged)
printf("Socket %d Priority-Tagged User Priority %d\n",
s, vl.upriority);
else
printf("Socket %d VLAN-Tagged VID %d User Priority %d\n",
s, vl.vid, vl.upriority);
}

NOTE: For the VLAN-tagged frame, if the returned VID value for getsockopt( ) is
0, it implies that the application uses the socket-based VLAN, chooses not to
configure the VID, and relies on the lower-layers (such as subnet-based VLAN or
MUX-L2) to insert the appropriate VID to the VLAN control information for the
outgoing VLAN-tagged frame.

552
23 Working with the 802.1Q VLAN Tag
23.7 VLAN Management

23.7.3 Subnet-Based VLAN Management

To support VLAN routing, FreeBSD uses the VLAN pseudo interface to


demultiplex VLAN tagged frames into logical VLAN network interfaces. This
technique has been adapted to the Wind River Network Stack to support
subnet-based VLAN configuration.
Each VLAN pseudo interface on VxWorks is created at run-time using the
interface cloning technique. For each pseudo interface, you must use ifconfig to
assign a VLAN, a parent interface, and a numeric VID. The parent interface must
be a physical interface that is attached to the IP layer at the time you create the
VLAN pseudo interface.
A single parent interface can support multiple VLAN pseudo interfaces provided
that the pseudo interfaces have different VIDs. For each frame that is received or
transmitted, the MUX-L2 discards the frame if the receiving or transmitting port is
not a member of the VLAN. Therefore, the parent interface must be a member of
the VLAN for the VID assigned to the VLAN pseudo interface.
To support the VLAN pseudo interface configuration, the ifconfig utility has been
extended to support the following options:
vlann create
Create the specified VLAN pseudo interface. Two forms of interface naming
style are supported, a free-form naming style and a more restrictive naming
style.
– The free-form VLAN pseudo interface naming style lets you specify the
VID and parent interface using the following format:
ifconfig nameY.X create
Where nameY is the name of the parent interface associated with the
VLAN pseudo interface and X is the VID for the VLAN pseudo interface.
This compact format eliminates the additional steps for specifying the
parent interface and the VID using the vlan and vlandev options. The
parent interface, nameY, must be a member of the VLAN specified by X.
Otherwise, this command will fail. 23

– The more restrictive naming style requires that the name of the VLAN
pseudo interface be in the format of vlannumber where number denotes the
unit number. If the interface is given without a unit number, the system
tries to create a new interface with an arbitrary unit number. Using this
more restrictive naming style, the VID and the association with the parent
interface must be specified with vlan and vlandev options.

553
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

vlann destroy
Destroy the specified VLAN pseudo interface.
vlann vlan vlan_tag
If vlann is a VLAN pseudo interface, set the VLAN tag value to vlan_tag. This
value is a 16-bit number that is used to create an 802.1Q VLAN header for
frames sent from the VLAN pseudo interface. Note that if an ifconfig call
contains the vlan option, you must set the vlandev in the same call.
vlandev iface
If the interface is a VLAN pseudo interface, associate it with the physical
interface, iface. Frames transmitted through the VLAN pseudo interface will be
diverted to the specified physical interface, iface, with 802.1Q VLAN
encapsulation by the MUX-L2. Frames with 802.1Q encapsulation received by
the parent interface with the correct VLAN tag will be diverted to the
associated VLAN pseudo interface. The VLAN pseudo interface is assigned a
copy of the parent interface's flags and the parent's Ethernet address.
Note that if an ifconfig( ) call contains the vlandev option, it must also use the
vlan option. The parent interface must be a member of the VLAN specified by
vlan_tag. Otherwise, this command will fail. If the VLAN pseudo interface
already has a physical interface associated with it, this command will also fail.
To change the association to another physical interface, the existing association
must first be cleared.
-vlandev iface
If the interface is a VLAN pseudo interface, this option disassociates it from the
physical interface, iface. This breaks the link between the VLAN pseudo
interface and its parent, clears its VLAN flag, its interface flags, its link
address, and shuts down the interface.
FreeBSD uses a link0 flag to indicate whether the parent interface supports the
insertion and extraction of a VLAN tag. VxWorks does not support this flag.
In fact, this flag is not required on VxWorks because when a port is attached to
the MUX-L2, the MUX-L2 will make the determination if the underlying
hardware supports VLAN insertion and extraction.
upriority user_priority
This option is a VxWorks-specific feature, not a ported Free BSD feature. If the
interface is a VLAN pseudo interface, set the VLAN user priority to
user_priority. This value, a 3-bit 802.1P user priority, is inserted to the 802.1Q
VLAN header for frames sent from the VLAN pseudo interface. Note that the
802.1P user priority is optional but the VLAN ID is mandatory. If you do not
specify a user_priority, it defaults to 0.

554
23 Working with the 802.1Q VLAN Tag
23.7 VLAN Management

Consequences of Changing the VID (applies to subnet VLAN only)

Be aware that changing the VID for the VLAN pseudo interface does not
automatically remove the parent interface from the VLAN membership associated
with the old VID. It also does not automatically add the parent interface to the
member set specified by the new VID. Therefore, the parent interface must be a
member of the VLAN specified by the new VID before the new VID can be
assigned. The parent interface remains a member of the VLAN specified by the old
VID unless the membership is explicitly removed.

Examples of Subnet-based VLAN Management

The following provides examples of creating VLAN pseudo interfaces. The first
examples rely on the compact interface naming style. The examples after that rely
on the restrictive interface naming style.

Examples Using the Compact Creation API

The following example uses the compact interface naming style to create a VLAN
pseudo interface fei1.50 with IP Address 190.0.2.234/24. It also specifies the parent
interface fei1 and VID 50 for the VLAN pseudo interface. It is assumed that fei1 is
already attached to the MUX-L2 and is a member of VLAN 50. Use l2config or
muxL2Ioctl( ) with the MUXL2IOCSVLANJOIN control command to join fei1 to
VLAN 50.
-> ifconfig "fei1.50 create inet 190.0.2.234/24"
value = 0 = 0x0
-> ifconfig "fei1.50"
fei1.50: flags=48043<UP,BROADCAST,RUNNING,MULTICAST,INET_UP> mtu 1496
inet 190.0.2.234 netmask 0xffffff00 broadcast 190.0.2.255
ether 00:08:c7:c9:24:76
vlan: 50 user priority: 0 parent interface: fei1
value = 0 = 0x0

The following example destroys the fei1.50 VLAN pseudo interface previously
created.
23
-> ifconfig "fei1.50 destroy"
value = 0 = 0x0

The following example uses the compact interface naming style to create a VLAN
pseudo interface, fei0.20, with IP Address 190.0.4.234/24. It also specifies the
parent interface fei0, VID 20, and user priority 5 for the VLAN pseudo interface. It
is assumed that fei0 is already attached to the MUX-L2 and is a member of VLAN
20. Use l2config or muxL2Ioctl( ) with the MUXL2IOCSVLANJOIN control
command to join fei0 to VLAN 20.

555
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

-> ifconfig "fei0.20 create"


value = 0 = 0x0

-> ifconfig "fei0.20 190.0.4.234/24"


value = 0 = 0x0

-> ifconfig "fei0.20 upriority 5"


value = 0 = 0x0

-> ifconfig "fei0.20"


fei0.20: flags=48043<UP,BROADCAST,RUNNING,MULTICAST,INET_UP> mtu 1496
inet 190.0.4.234 netmask 0xffffff00 broadcast 190.0.4.255
ether 00:03:47:b0:d7:17
vlan: 20 user priority: 5 parent interface: fei0
value = 0 = 0x0

Examples Using the Name-Restrictive Creation API

The following example creates a VLAN pseudo interface, vlan0, with IP Address
190.0.2.123/24, assigns the pseudo interface with VID 20 and associates it with the
parent interface fei1. It is assumed that fei1 is attached to the MUX-L2 and is a
member of VLAN 20. Use l2config or muxL2Ioctl( ) with the
MUXL2IOCSVLANJOIN control command to join fei1 to VLAN 20.
-> ifconfig "vlan0 create"
value = 0 = 0x0

-> ifconfig "vlan0"


vlan0: flags=0 mtu 1500
ether 00:00:00:00:00:00
vlan: 0 user priority: 0 parent interface: <none>
value = 0 = 0x0

-> ifconfig "vlan0 vlan 20 vlandev fei1"


value = 0 = 0x0

-> ifconfig "vlan0 190.0.2.123/24"


value = 0 = 0x0

-> ifconfig "vlan0"


vlan0: flags=48043<UP,BROADCAST,RUNNING,MULTICAST,INET_UP> mtu 1496
inet 190.0.2.123 netmask 0xffffff00 broadcast 190.0.2.255
ether 00:08:c7:c9:24:76
vlan: 20 user priority: 0 parent interface: fei1
value = 0 = 0x0

The following example creates a VLAN pseudo interface, vlan1, with IP Address
190.0.3.234/24, assigns the pseudo interface with VID 50, user priority 7 and
associates it with the parent interface fei0. It is assumed that fei0 is attached to the
MUX-L2 and is a member of VLAN 50. Use l2config or muxL2Ioctl( ) with the
MUXL2IOCSVLANJOIN control command to join fei0 to VLAN 50.
-> ifconfig "vlan1 create"

556
23 Working with the 802.1Q VLAN Tag
23.7 VLAN Management

value = 0 = 0x0

-> ifconfig "vlan1"


vlan1: flags=0 mtu 1500
ether 00:00:00:00:00:00
vlan: 0 user priority: 0 parent interface: <none>
value = 0 = 0x0

-> ifconfig "vlan1 vlan 50 upriority 7 vlandev fei0"


value = 0 = 0x0

-> ifconfig "vlan1 190.0.3.234/24"


value = 0 = 0x0

-> ifconfig "vlan1"


vlan1: flags=48043<UP,BROADCAST,RUNNING,MULTICAST,INET_UP> mtu 1496
inet 190.0.3.234 netmask 0xffffff00 broadcast 190.0.3.255
ether 00:03:47:b0:d7:17
vlan: 50 user priority: 7 parent interface: fei0
value = 0 = 0x0

The following example destroys the vlan1 VLAN pseudo interface previously
created.
-> ifconfig "vlan1 destroy"
value = 0 = 0x0

NOTE: Be aware that destroying a VLAN pseudo interface does not automatically
remove the parent interface from the VLAN associated with the VLAN pseudo
interface. You must make an explicit call either to l2config or to muxL2Ioctl( ) with
MUXL2IOCSVLANLEAVE to remove the parent interface from the previous VLAN
membership.

23.7.4 Simultaneous Subnet-Based and Socket-Based VLANs

For subnet-based VLANs to co-exist with socket-based VLANs, Wind River has
enhanced the implementation of the output routine for the VLAN pseudo interface
by applying the following rules:
23

If the frame does not contain any VLAN control information (that is, the VID
and user priority are not specified), the VID and user priority configured for
the VLAN pseudo interface will be assigned to the frame.

If the frame specifies a valid VID value (that is, the VID specifies any value
from 1 to 4094), the VLAN pseudo interface will not change the VLAN control
information in the frame. In other words, the socket-based VLAN
configuration takes precedence over the subnet-based VLAN configuration.

557
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

As long as the VID is specified, the VLAN pseudo interface assumes the frame
also carries a valid user priority assignment. If the frame contains user priority
assignment only (that is, the VID is zero), the VID configured for the VLAN
pseudo interface is applied the frame. The VLAN pseudo interface will not
override the user priority specified by the socket-based VLAN.

If the frame specifies a priority-tagged frame, the VLAN pseudo interface will
not change the VLAN control information in the frame.

23.8 Using the MUX-L2 Show Routines


For debugging and diagnostic purposes, the MUX-L2 provides muxL2Show( ),
muxL2StatShow( ), muxL2VlanShow( ), and muxL2VlanStatShow( ).

Example 23-1 muxL2Show( )

Call muxL2Show( ) to display the configuration of ports registered to the MUX-L2.


-> muxL2Show
max number of physical ports: 16
max number of vlans device supports: 16
number of vlans configured in device: 3
number of ports attached to MUX-L2: 2

Device: <fei> Unit: <1> L2 Port Object: 0x10cc040 endObjId: 1


Port VID (PVID): 1 Port User Priority: 0
Port ingress filter: TRUE
Port ingress acceptable frame filter type: Admit vlan-tagged frames only
Hardware supports vlan tagging: FALSE
Hardware supports vlan mtu: FALSE
Number of vid configured for the port: 2
Port VLAN membership:
VID 1 Egress: untagged-tagged
VID 20 Egress: vlan-tagged

Device: <fei> Unit: <0> L2 Port Object: 0x10e40a0 endObjId: 2


Port VID (PVID): 1 Port User Priority: 0
Port ingress filter: TRUE
Port ingress acceptable frame filter type: Admit All Frames
Hardware supports vlan tagging: FALSE
Hardware supports vlan mtu: FALSE
Number of vid configured for the port: 2
Port VLAN membership:
VID 1 Egress: untagged-tagged
VID 100 Egress: vlan-tagged
value = 1 = 0x1

558
23 Working with the 802.1Q VLAN Tag
23.8 Using the MUX-L2 Show Routines

Example 23-2 muxL2VlanShow( )

Calls muxL2VlanShow( ) to display the VLAN configurations maintain by the


MUX-L2 on a per-VLAN basis.
-> muxL2VlanShow

VLAN 1: Number of Members: 2 Egress Untagged: 2


VLAN 20: Number of Members: 1 Egress Untagged: 0
VLAN 100: Number of Members: 1 Egress Untagged: 0

Port to device name mapping:


Port 1 -> fei1
Port 2 -> fei0

VLAN Membership information:


(Legend: 'M' = Member '-' = Unspecified)
VLAN 1 : MM--------------
VLAN 20 : M---------------
VLAN 100 : -M--------------

VLAN Egress Frame Type:


(Legend: 'T' = Vlan-Tagged 'U' = Untagged '-' = Unspecified)
VLAN 1 : UU--------------
VLAN 20 : T---------------
VLAN 100 : -T--------------

value = 1 = 0x1

Example 23-3 muxL2StatShow( ) and muxL2VlanStatShow( )

The MUX-L2 also maintains various VLAN statistics on a per-port per-VLAN


basis. These statistics are disabled by default for performance reasons. To include
these statistics, compile MUX-L2 with the MUX_L2_VLAN_STATS define. If VLAN
statistics are included, muxL2VlanStatShow( ) and muxL2StatShow( ) can be
used to monitor the traffic on a per-port per-VLAN basis.
-> muxL2StatShow
fei1 Port Statistics:
Number of received frames discarded due to non-vlan
reasons (i.e. Discard Ingress Filtering): 9
Number of egress frames discarded due to Egress
Rules violation: 0
23
VLAN 1 staticstics:
Number of frames received: 0
Number of frames transmitted: 0
Number of received frames discarded: 0

VLAN 20 staticstics:
Number of frames received: 166
Number of frames transmitted: 226
Number of received frames discarded: 0

559
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

fei0 Port Statistics:


Number of received frames discarded due to non-vlan
reasons (i.e. Discard Ingress Filtering): 0
Number of egress frames discarded due to Egress
Rules violation: 0

VLAN 1 staticstics:
Number of frames received: 0
Number of frames transmitted: 0
Number of received frames discarded: 0

VLAN 100 staticstics:


Number of frames received: 393
Number of frames transmitted: 486
Number of received frames discarded: 0

value = 0 = 0x0

-> muxL2VlanStatShow
fei1 VLAN 1 staticstics
Number of frames received: 0
Number of frames transmitted: 0
Number of received frames discarded: 0

fei0 VLAN 1 staticstics


Number of frames received:
Number of frames transmitted: 0
Number of received frames discarded: 0

fei1 VLAN 20 staticstics


Number of frames received: 166
Number of frames transmitted: 226
Number of received frames discarded: 0

fei0 VLAN 100 staticstics


Number of frames received: 393
Number of frames transmitted: 486
Number of received frames discarded: 0

value = 0 = 0x0

23.9 Using the Deprecated VLAN Tag Library


Although deprecated, the vlanTagLib API is, for the most part, still supported in
this release. The following information is included as a convenience for developers
working with legacy software. However, any new development should use the
802.1Q VLAN tag functionality now integrated with the MUX.

560
23 Working with the 802.1Q VLAN Tag
23.9 Using the Deprecated VLAN Tag Library

Backward Compatibility

To include the old vlanTagLib library in a image, use the INCLUDE_VLAN_TAG


configuration component. To ensure that this component is available for inclusion,
you must build the network stack code with -DVLAN_TAG. For information on
building the network stack, see your Wind River Platforms Getting Started.
In addition, due to internal changes, you must recompile any code that previously
used routines from vlanTagLib.

Configuration Overview

To set up an interface for the 802.1Q VLAN tag, you must call ipVlanTagAttach( )
after the ipAttach( ) and/or ip6Attach( ) calls for the interface. The
ipVlanTagAttach( ) call determines whether the interface receives tagged,
priority-tagged, and/or untagged frames. It also registers ipVlanTagOutput( ) as
the output routine for the interface. This output routine has been written to
recognize the VLAN tagging mechanism.
After this initial configuration, you can specify the acceptable ingress frame type
filter, the ingress rules, the egress frame type filter, and the egress rules.
Optionally, you may need to set a VLAN ID value or a priority bits value.
In outline, the sequence of calls needed to configure an interface for VLAN tagged
frames is as follows:
1. Attach IPv4 or IPv6 to the interface: ipAttach( ) or ip6Attach( ).
2. Configure the interface to handle VLAN tagging: ipVlanTagAttach( ).
3. Set the acceptable ingress frame type filter: vlanTagIfIngressTypeSet( ).
If you do not explicitly specify the ingress frame type filter, it defaults to
VLAN_INGRESS_ALL_FRAMES, which configures the device to accept all
tagged, untagged, and priority-tagged frames.
4. Set the egress frame type filter: vlanTagIfEgressTypeSet( )
23
If you do not explicitly specify the egress frame type filter, it defaults to
VLAN_EGRESS_UNTAGGED_FRAMES, which configures the interface to
transmit untagged frames. This default egress behavior maintains backward
compatibility with frame transmission on VLAN-unaware interfaces (that is,
interfaces for which you have not called the ipVlanTagAttach( ) routine).
5. Optionally, adjust the ingress rules behavior: vlanTagIfIngressRulesSet( )

561
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

6. Set the VLAN ID, or set the priority bits value, or allow TOS-to-priority bits
translation: vlanTagIfVidSet( ) or vlanTagIfPriorityBitsSet( ) or
vlanTagIfEgressRulesSet( ) for the VLAN_EGRESS_IP_TOS rule.
7. Optionally, adjust the egress rules behavior: vlanTagIfEgressRulesSet( ).
8. Already mentioned in the previous step is a vlanTagIfEgressRulesSet( ) call
to activate the VLAN_EGRESS_IP_TOS rule.
9. Configure the IP address for the interface: ifconfig( )

23.9.1 Configuring the Acceptable Ingress Frame Type Filter

Use the vlanTagIfIngressTypeSet( ) routine to configure the Acceptable Ingress


Frame Type for an interface. This filter applies to every frame it receive on the
interface. If you do not define this filter, it defaults to
VLAN_INGRESS_ALL_FRAMES. The valid filters are as follows:

VLAN_INGRESS_TAGGED_FRAMES
Accept only those frames explicitly tagged with a VLAN ID. All untagged and
priority-tagged frames are discarded.
VLAN_INGRESS_ALL_FRAMES
Accept all frames (tagged, untagged, and/or priority-tagged). This is the
default value. It applies if you do not explicitly specify a filter for an interface.

23.9.2 Configuring the Egress Frame Type Filter

Use the vlanTagIfEgressTypeSet( ) routine to specify the egress frame type filter
for an interface. Using this filter, you can specify whether the interface transmits
tagged frames, priority-tagged frames, or untagged frames. If you do not define
this filter, it defaults to VLAN_EGRESS_UNTAGGED_FRAMES. The valid egress
frame type filters are as follows:
VLAN_EGRESS_TAGGED_FRAMES
Send tagged frames with non-zero VLAN IDs only.
VLAN_EGRESS_PRIORITY_FRAMES
Send priority-tagged frames with a VLAN ID of zero. For more on how to
configure the value of the priority bits, see 23.9.4 Configuring the Egress Rules,
p.563.

562
23 Working with the 802.1Q VLAN Tag
23.9 Using the Deprecated VLAN Tag Library

VLAN_EGRESS_UNTAGGED_FRAMES
Send untagged frames only. If the interface was previously configured to send
tagged or priority-tagged frames, this flag undoes that interface configuration
to send frames without any tag at all. This default applies when no value is
specified.

23.9.3 Configuring the Ingress Rules

Use the vlanTagIfIngressRulesSet( ) routine to configure the ingress rules that


apply after a frame passes the type filter. Ingress rules apply based on a
comparison of the VLAN ID found in the frame and the VLAN ID assigned to the
receiving interface (or the system VLAN ID, if there is no interface-specific VLAN
ID).
If there is a mismatch of VLAN IDs, the interface typically discards the frame. To
override this behavior, use an ingress rule. Currently, there is only one valid rule:
VLAN_INGRESS_SKIP_TAG
Ignore the VLAN tagged header if present. If there is mismatch of VLAN IDs,
the frame is not discarded.

23.9.4 Configuring the Egress Rules

Depending on the egress filter, the egress rules determine the contents of the
VLAN tag (if any) and then add that tag to the header of an outgoing frame.

Setting the CFI Bit

By default, the egress rules do not set the CFI bit. This indicates Ethernet. To
activate the rule that sets the CFI bit in outgoing frames, use
vlanTagIfEgressRulesSet( ) to activate the VLAN_EGRESS_CFI_SET rule. Whether
or not you activate the VLAN_EGRESS_CFI_SET rule, keep in mind that
vlanTagLib does not check whether the setting for CFI bit is appropriate for the
type of interface used. 23

VLAN Tagged Frames Include a VLAN ID

If the frame filter type is set to VLAN_EGRESS_TAGGED_FRAMES, the egress rules


insert a tag containing the VLAN ID for the interface. To specify the VLAN ID for
an interface, call vlanTagIfVidSet( ). If you do not assign a VLAN ID to an
interface, the system-wide default VLAN ID is added to the frame header. Use
vlanTagSysDefaultVidSet( ) to set the system-wide default VLAN ID.

563
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Priority Tagged Frames Include an 802.1P Priority Value

The 3-bit priority value in the VLAN header can be configured using one of the
following methods:
1. Use vlanTagIfPriorityBitsSet( ) to configure the priority bits value that will be
used for all the egress frames on this interface.
2. Use vlanTagIfEgressRulesSet( ) to set the VLAN_EGRESS_IP_TOS egress rule
for the interface. This allows the IP TOS to 802.1P priority conversion. The
priority value configured for the interface (if any) will be ignored. To use this
option, a user-defined conversion function pointer must be registered via the
vlanTagIfTosToPriorityRegister( ) routine. This user-defined conversion
routine will be invoked with the current IP TOS value extracted from the IP
header. The conversion routine must return the proper 802.1P priority level
that will be assigned to the 3-bit VLAN priority field in the VLAN tag.

23.9.5 VLAN Tagged Frame Configuration Examples

The following sections include specific examples of how to configure an interface


for an ID-based VLAN and for a VLAN based on priority bits.

Tagging Frames with VLAN IDs

The following example configures the motscc0 interface to use an IP Address of


10.10.1.127/24 and to transmit tagged VLAN frames using a VLAN ID of 100. The
example also explicitly configures the interface to accept all incoming frames:
tagged, untagged, or priority-tagged frames. Note that the call to ipAttach( ) is
required only if the interface was not previously attached to IP.
-> ipAttach (0, "motscc")
-> ipVlanTagAttach (0, "motscc", 1, 0, 0, 0)
-> vlanTagIfIngressTypeSet ("motscc", 0, VLAN_INGRESS_ALL_FRAMES, NULL)
-> vlanTagIfEgressTypeSet ("motscc", 0, VLAN_EGRESS_TAGGED_FRAMES, NULL)
-> vlanTagIfVidSet ("motscc",0, 100, NULL)
-> ifconfig ("motscc0 10.10.1.127 netmask 255.255.255.0")

Tagging Frames with a Fixed Priority Bits Value

The following example configures the motscc0 interface to use an IP Address of


10.10.1.127/24 and to transmit priority-tagged frames with the VLAN priority bits
set to 5. Note that, because the filter for the Acceptable Ingress Frame Type is not
explicitly configured, it defaults to accept all frames.

564
23 Working with the 802.1Q VLAN Tag
23.9 Using the Deprecated VLAN Tag Library

-> ipAttach (0, "motscc")


-> ipVlanTagAttach (0, "motscc", 1, 0, 0)
-> vlanTagIfEgressTypeSet ("motscc", 0, VLAN_EGRESS_PRIORITY_FRAMES, NULL)
-> vlanTagIfPriorityBitsSet ("motscc", 0, 5, NULL)
-> ifconfig ("motscc0 10.10.1.127 netmask 255.255.255.0")

Tagging Frames with a Priority Bits Value Translated from the IP TOS Value

The following example configures the motscc0 interface to use an IP Address of


10.10.1.127/24 and to transmit priority-tagged frames. The priority bits value is
generated by translating the IP TOS field to a VLAN priority bits value. This
assumes that other applications on the system are sending IP packets with the IP
TOS fields configured.
-> ipAttach (0, "motscc")
-> ipVlanTagAttach (0, "motscc", 1, 0, 0)
-> vlanTagIfEgressTypeSet ("motscc", 0, VLAN_EGRESS_PRIORITY_FRAMES, NULL)
-> vlanTagIfEgressRulesSet ("motscc", 0, VLAN_EGRESS_IP_TOS, NULL)
-> vlanTagIfPriorityBitsSet ("motscc", 0, 5, NULL)
-> ifconfig ("motscc0 10.10.1.127 netmask 255.255.255.0")

Undoing the VLAN Egress Configuration for an Interface

The following example unwinds the egress frame configuration for the interface to
send untagged frames only.
-> vlanTagIfEgressTypeSet ("motscc", 0, VLAN_EGRESS_UNTAGGED_FRAMES, NULL)

Checking the VLAN Tagging Configuration for an Interface

You can use the vlanTagIfShow( ) routine to display the interface VLAN tagging
information.

23

565
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

566
A
Glossary

A.1 Introduction 567


A.2 Terms 567
A.3 Abbreviations and Acronyms 573

A.1 Introduction
This chapter contains brief definitions of networking terms, acronyms, and
abbreviations used in discussions in this manual.

A.2 Terms
This section defines terms used in the Wind River Network Stack documentation.
It includes both standard industry terms and clarifies terms used in this book
whose meaning, in the context of this product, differs from another definition used
in the industry.

567
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

COMP protocol

The COMP protocol (Connection-Oriented Message Passing protocol) is a VxWorks


proprietary protocol (standard) by which local domain socket names are handled.
This protocol provides support for a reliable communication style that is
bidirectional and message-based.

datagram

A datagram is a self-contained packet used in packet switching. A datagram


contains enough information in the header to allow the network to forward it to
the destination independently of previous or future datagrams. Thus, no setup is
needed before a computer tries to send datagrams to a computer with which it has
not previously communicated, unlike with virtual circuit protocols. See also,
packet, p.570.

data link layer

The data link layer is the functionality in the OSI network model that transfers data
between adjacent network nodes in a wide area network or between nodes on the
same local area network segment. The data link layer prepares the packets for
transmission, and detects and handles errors, such as packet collision. Examples of
data link protocols are Ethernet for local area networks and PPP (Point-to-Point
Protocol) for point-to-point connections.

fast path

A fast path is a fast IP-forwarding mechanism that intercepts packets before they
are passed up to IP. If the packet is destined for a location known to the fast path
route cache (also known as the FIB, the Forwarding Information Base), the
application forwards the packet. If the destination is unknown to the FIB, the
application leaves the packet to IP.

firewall

A firewall is a piece of hardware or software used in a networked environment to


prevent communications that are forbidden by the security policy. A common type
of firewall is a router retrofitted with extra software for packet filtering based on a
list of rules or criteria.

egress filtering

Egress filtering is a method of securing a network by monitoring and filtering


packets that leave an internal network to external networks (internet) via a router.

568
A Glossary
A.2 Terms

Egress filtering makes a system less prone to attack from hackers by ensuring that
spoofed packets never leave an internal network. See also, ingress filtering, p.569.

END driver

An END driver is a frame-oriented drivers that exchange frames with the MUX. All
drivers now shipped with the standard network stack are ENDs. See also, NPT
driver, p.570 and MUX, p.570.

gif interface

A gif interface is a generic tunneling pseudo device for IPv4 and IPv6. It can tunnel
IPv[46] traffic over IPv[46]. Therefore, there can be four possible configurations.
The behavior of gif is mainly based on RFC2893 IPv6-over-IPv4 configured tunnel.
See also, stf interface, p.572.

ingress filtering

Ingress filtering is the application of a firewall rulebase to inbound traffic. Ingress


filtering allows you to control the traffic that enters your network and restrict
activity to legitimate purposes. See also, egress filtering, p.568 and firewall, p.568.

IPv6

IPv6 stands for Internet Protocol version 6, the latest level of the Internet Protocol.
The most obvious improvement in IPv6 over the IPv4 is that IP addresses are
lengthened from 32 bits to 128 bits. This extension anticipates future growth of the
Internet and provides relief for what was perceived as an impending shortage of
network addresses.

jumbogram

A jumbogram is a transmission packet that contains a payload larger than 65,535


eight-bit bytes (also known as octets). IPv6 is able to carry a jumbogram.

MAC

MAC (Medium Access Control) is the part of the data link layer that governs access
to the transmission media and is the method of determining which device has A
access to the Ethernet collision domain at any given time. See data link layer, p.568.

MAC Interface

The MAC interface is the Ethernet interface used by the SNMP agent in the network
device for communications to and from another device.

569
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

MLD

Multicast Listener Discovery (MLD) is one of the protocols needed to support


multicasting in the IPv6 domain.

MUX

The MUX is an interface layer through which the network services communicate
with the data link layer. MUX decouples the network driver and network protocol
layers, thereby allowing you to add new network drivers without having to alter
the network protocol, or to add a new network protocol without having to alter the
MUX_based network interface drivers. Currently, the MUX supports two network
driver interface styles, the END interface and the Network Protocol Toolkit (NPT)
driver interface. Se e also, END driver, p.569 and NPT driver, p.570.

NPT driver

An NPT driver is an implementation of the OSI Data link layer that makes use of
MUX functions. The NPT (Network Protocol Toolkit) style drivers are
packet-oriented drivers that exchange packets with the MUX. See also, END driver,
p.569 and MUX, p.570.

OSI network model

The OSI network model is a description of seven layers through which data passes
when it is transmitted from an application on one machine to a peer on a remote
but network-connected machine. In practice, only four layers are usually
implemented: the application layer, the transport layer, the network layer, and the
data link layer.

packet

A packet is a collection of bits, comprising data and control information—including


a header, which contains the packet’s source and destination IP addresses—
formatted for transmission, by protocols, from one node to another.

packet filtering

Packet filtering is the selective passing or blocking of data packets as they pass
through a network interface, specifically between the network and transport
layers. The most commonly-used criteria when inspecting packets are source and
destination address, source and destination port, and protocol. Filter rules specify
the criteria that a packet must match and the resulting action taken.

570
A Glossary
A.2 Terms

protocol

A network protocol is a standardized format for communication or data


transmission between two devices. For example, network protocol rules can
specify the packet format, data compression, timing, sequencing, and error
checking for data transmission. A given protocol usually applies to software and
hardware elements operating at the same OSI layer. However, a protocol can be
used to mean a set or suite of protocols that can span layers, as in the case of
TCP/IP. See also, OSI network model, p.570 and TCP/IP, p.572.

RFCs

RFCs (Request for Comments) are publicly available documents that contain
research, innovations, and methodologies applicable to Internet technologies. The
Internet Engineering Task Force (IETF) adopts some of the applied information
theory published in RFCs as Internet standards.

router

A router is a device that determines which paths to use through a network to


transmit data. Routers operate at the network layer in the OSI model, providing
intelligent connections between networks.

SACK

A SACK is a Selective Acknowledgement used by SCTP, indicating any gaps in the


transmission. TCP does not make explicit use of SACKs, but can be configured to
support them. However, TCP can only report four missing data packets in a SACK,
whereas SCTP allows for much larger amounts to be reported.

SNARF protocol

A SNARF protocol is a protocol that sees all packets first and that acts as a filter for
other protocols, by determining whether or not a packet is passed on.

socket

An internet socket is one end-point of a two-way communication link used by


programs to communicate over a network. An internet socket is identified by a A
unique number defined by the TCP/IP protocol (for example, a combination of an
IP address, a protocol, and a port number). Sockets provide information to the
transport layer protocol. Data written by a program to the socket at one end of the
connection is transmitted to the socket on the other end of the connection, where it
can be read by the program at that end.

571
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

spoofing

Spoofing, or Internet Protocol spoofing (IP spoofing), is the creation of IP packets


with a forged, that is, spoofed, source IP address.

stf interface

An stf interface is a 6to4 tunnel interface that can tunnel IPv6 traffic over IPv4, as
specified in RFC3056. For ordinary nodes in 6to4 site, you do not need stf interface.
The stf interface is necessary for site border router (called "6to4 router" in the
specification). See also, gif interface, p.569.

TCP/IP

TCP/IP is a suite of communication protocols that includes TCP and IP. It is used
to connect hosts on the Internet and is built into the UNIX operating system. See
also, protocol, p.571.

transport layer

The transport layer is the functionality in the OSI network model that provides
transparent, reliable, and cost-effective transfer of data between end users. The
transport layer controls the reliability of a given link, keeping track of the packets
and retransmitting those that fail. TCP, UDP, RTP, and SCTP (listed in Abbreviations
and Acronyms, p.573) are examples of transport layer protocols. See also, OSI
network model, p.570.

tunneling

A tunneling protocol is a network protocol that encapsulates one protocol or


session inside another. Tunneling can be used to transport a network protocol
through a network that would not otherwise support it. Corporations make use of
tunneling to extend the corporate network through private “tunnels” over the
public Internet. This kind of interconnection is known as a virtual private network
(VPN) and can provide functionality such as private addressing.

UDP

UDP, which stands for User Datagram Protocol, is a relatively fast and
connectionless protocol that runs at the transport layer on top of IP networks.
Because it has very few error recovery services (unlike TCP), it is used primarily
for broadcasting messages and for other applications that do not require a
connection. See also, datagram, p.568, protocol, p.571, and transport layer, p.572.

572
A Glossary
A.3 Abbreviations and Acronyms

A.3 Abbreviations and Acronyms


The Wind River Network Stack uses the following abbreviations and acronyms in
development tools, code, file names, and directory names.

Table A-1 Abbreviations and Acronyms

Abreviation Description

ARP Address Resolution Protocol

BFP BSD (Berkeley) Packet Filter

BGP Border Gateway Protocol

BOOTP Bootstrap Protocol

CBQ Class-Based Queueing

CIDR Classless Inter-domain Routing

COMP Connection-Oriented Message Passing

CSMA Carrier Sense Multiple Access

DHCP Dynamic Host Configuration Protocol

DNS Domain Name System

ECN Explicit Congestion Notification

EGP Exterior Gateway Protocol

END Enhanced Network Driver

FIB Forwarding Information Base

FTP File Transfer Protocol

GTF Generalized Timing Format?

HFSC Hierarchical Fair Service Curve A

HTTP Hypertext Transfer Protocol

IETF Internet Engineering Task Force

IANA Internet Assigned Number Authority

573
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Table A-1 Abbreviations and Acronyms

Abreviation Description

ICMP Internet Control Message Protocol

IGMP Internet Group Management Protocol

IGP Interior Gateway Protocol

IP Internet Protocol

IPC Inter-Process Communication

IPSec IP Security

LAN Local Area Network

MAC Media Access Control

MIB Management Information Base

MII Media Independent Interface

MLD Multicast Listener Discovery

NAT Network Address Translation

NDP Neighbor Discovery Protocol

NFS Network File System

NPT Network Protocol Toolkit

OSI Open Systems Interconnection

OSPF Open Shortest Path First

PIM Protocol Independent Multicasting

PSTN Public Switched Telephone Network

RARP Reverse Address Resolution Protocol

RED Random Early Detection

RFC Request for Comment

RIP Routing Information Protocol

574
A Glossary
A.3 Abbreviations and Acronyms

Table A-1 Abbreviations and Acronyms

Abreviation Description

RPC Remote Procedure Call

RTO Retransmission Time Out

RTP Real-time Transport Protocol

SACK Selective Acknowledgement

SAL Socket Application Library

SCTP Stream Control Transmission Protocol

SMTP Simple Mail Transfer Protocol

SNMP Simple Network Management Protocol

SNS Socket Name Service

SNTP Simple Network Time Protocol

TCP Transmission Control Protocol

TFTP Trivial File Transfer Protocol

TOS Type of Service

TTL Time to Live

UDP User Datagram Protocol

VLAN Virtual Local Area Network

VPN Virtual Private Network

XDR External Data Representation

575
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

576
B
MUX/NPT Routines and Data
Structures

B.1 Introduction 577


B.2 MUX Routines 577
B.3 Data Structures 593

B.1 Introduction
This appendix describes the routines and data structures that comprise the
MUX/NPT API.

B.2 MUX Routines


This section provides descriptions of the following routines:
muxAddrResFuncAdd( ) deprecated, use muxIfFuncAdd( )
muxAddrResFuncDel( ) deprecated, use muxIfFuncDel( )
muxAddrResFuncGet( ) deprecated, use muxIfFuncGet( )
muxAddressForm( )
muxBind( ) deprecated, use muxTkBind( )

577
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

muxDevExists( )
muxDevLoad( )
muxDevStart( )
muxDevStop( )
muxDevUnload( )
muxError( )
muxIfFuncAdd( )
muxIfFuncDel( )
muxIfFuncGet( )
muxIoctl( )
muxMCastAddrAdd( )
muxMCastAddrDel( )
muxMCastAddrGet( )
muxTkBind( )
muxTkDrvCheck( )
muxTkPollReceive( )
muxTkPollSend( )
muxTkReceive( )
muxTkSend( )
muxTxRestart( )
muxUnbind( )

B.2.1 muxAddrResFuncAdd( )

NOTE: This routine is still supported but deprecated for future use. Its internals
have been replaced with a call to muxIfFuncAdd( ), the currently preferred API.

STATUS muxAddrResFuncAdd
(
long ifType, /* interface type from m2Lib.h, or driver type */
long protocol, /* protocol from RFC 1700, or service type */
FUNCPTR addrResFunc /* the routine being added. */
)
{
return (muxIfFuncAdd (ifType, protocol, ADDR_RES_FUNC, addrResFunc));
}

578
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

B.2.2 muxIfFuncAdd( )

Use muxIfFuncAdd( ) to provide the MUX with pointers to protocol/driver bind


service routines. These service routines are particular to a protocol/driver binding.
Currently, muxIfFuncAdd( ) lets you specify up to three different bind service
routines for a protocol/driver bind instance:

an address resolution routine
■ a multicasting address resolution routine
■ an output routine
For standard Ethernet drivers bound to IPv4 or IPv6, the MUX supplies default
protocol/driver bind service routines for address resolution, multicast address
resolution, and output.
STATUS muxIfFuncAdd
(
long ifType, /* Media interface type, from m2Lib.h */
long protocol, /* Service type, for instance from RFC 1700 */
int funcType, /* type of function being added */
FUNCPTR ifFunc /* Function to call. */
)

ifType
Expects a media interface or network driver type, such as can be found in
m2Lib.h.
protocol
Expects a network service or protocol type, such as can be found in RFC 1700.
Look for the values under ETHER TYPES. For example, Internet IP would be
identified as 2048 (0x800 hexadecimal).
funcType
Currently, the supported routine types are ADDR_RES_FUNC,
IF_OUTPUT_FUNC, and MULTI_ADDR_RES_FUNC. For example, the routines
registered (by default) for Ethernet drivers bound to IPv4 are arpResolve( ),
ether_output( ), and ether_resolvemulti( ) respectively. When writing
equivalents to these routines, your routines must match these routines in
prototype. If you are interested in tunneling, look at tunnelIfOutput( ), which
is defined in tunnelLib.
ifFunc
Expects a pointer to a routine for this combination of driver type and service B
type.

579
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NOTE: If using the NPT architecture, the ifType and protocol arguments are not
restricted to the m2Lib.h or RFC 1700 values.

B.2.3 muxAddrResFuncDel( )

NOTE: This routine is still supported but deprecated for future use. Its internals
have been replaced with a call to muxIfFuncDel( ), the currently preferred API.

STATUS muxAddrResFuncDel
(
long ifType, /* ifType of function you want to delete */
long protocol, /* protocol from which to delete the function */
)
{
return (muxIfFuncDel (ifType, protocol, ADDR_RES_FUNC));

B.2.4 muxIfFuncDel( )

Use muxIfFuncDel( ) to undo the assignment of a protocol/driver bind service


routine to an interface-type/protocol bind instance.
STATUS muxIfFuncDel
(
long ifType, /* media interface type from m2Lib.h */
long protocol, /* protocol type, for instance from RFC 1700 */
int funcType /* type of function to delete. */
)

Valid values for funcType are ADDR_RES_FUNC, IF_OUTPUT_FUNC, and


MULTI_ADDR_RES_FUNC. For more information on these routine types, see
B.2.2 muxIfFuncAdd( ), p.579.
The muxIfFuncDel( ) routine returns OK, on success; or ERROR, if the request
fails.

B.2.5 muxAddrResFuncGet( )

NOTE: This routine is still supported but deprecated for future use. Its internals
have been replaced with a call to muxIfFuncGet( ), the currently preferred API.

580
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

STATUS muxAddrResFuncGet
(
long ifType, /* ifType of function you want to delete */
long protocol, /* protocol from which to delete the function */
)
{
return (muxIfFuncGet (ifType, protocol, ADDR_RES_FUNC));
}

B.2.6 muxIfFuncGet( )

Use muxIfFuncGet( ) to retrieve a pointer to a protocol/driver bind service


routine bound to a particular interface-type/protocol bind instance.
FUNCPTR muxIfFuncGet
(
long ifType, /* media interface type from m2Lib.h */
long protocol, /* protocol type, for instance from RFC 1700 */
int funcType /* type of function to get */
)

Valid values for funcType are ADDR_RES_FUNC, IF_OUTPUT_FUNC, and


MULTI_ADDR_RES_FUNC. For more information on these routine types, see
B.2.2 muxIfFuncAdd( ), p.579.
This routine returns a pointer to the requested routine, or NULL if no routine is
registered for the service.

B.2.7 muxAddressForm( )

Use muxAddressForm( ) to form a frame with a link-layer address. A network


service needs this routine when working with ENDs, which are frame-oriented,
but not with NPT drivers, which are packet oriented.
When given the source and destination addressing information (through pSrcAddr
and pDstAddr), this routine returns an mBlk that points to an assembled link-level
header, and prepends this header to the mBlk chain pointed to by pMblk. Note that
the pDstAddr.mBlkHdr.reserved field should be set to the network protocol type.
M_BLK_ID muxAddressForm
(
void * pCookie, /* the cookie returned by muxBind() */ B
M_BLK_ID pMblk, /* pointer to the packet being reformed */
M_BLK_ID pSrcAddr, /* pointer to the mBlk with the source address */
M_BLK_ID pDstAddr, /* pointer to the mBlk with the dest address */
)

581
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This routine returns the head of an mBlk chain containing the data from pMblk
with a prepended link-level header, or NULL if the attempt fails.

B.2.8 muxBind( )

NOTE: This routine is deprecated for future use. Use muxTkBind( ) instead.

You can use muxBind( ) to bind a network service to an END. It is often better to
use muxTkBind( ), which works with both ENDs and NPT drivers.
void * muxBind
(
char * pName, /* interface name, for example, ln, ei,... */
int unit, /* unit number */
BOOL (* stackENDRcvRtn)(void *, long, M_BLK_ID, LL_HDR_INFO *, void *),
STATUS (* stackENDShutdownRtn)(void *, void *),
STATUS (* stackENDRestartRtn)(void *, void *),
void (* stackENDErrorRtn)(END_OBJ *, END_ERR *, void *),
long type, /* protocol type, from 1700 or user-defined */
char * pProtoName, /* string name for protocol */
void * pSpare /* identifies the binding instance */
)

Note that the stack*Rtn routines in the parameter list are defined differently than
in muxTkBind( ).
The muxBind( ) routine returns a cookie identifying the network driver to which
the MUX has bound the service. The service should keep track of this cookie for
use with other MUX routines.

B.2.9 muxDevExists( )

Use muxDevExists( ) to test whether a given device has already been loaded into
the network stack. As input, it expects the name and unit number of the device to
be tested.
BOOL muxDevExists
(
char * pName, /* string containing a device name (ln, ei, ...)*/
int unit /* unit number */
)

This routine returns TRUE if the device has already been loaded into the network
stack, or FALSE otherwise.

582
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

B.2.10 muxDevLoad( )

Use muxDevLoad( ) to load a network driver into the MUX. Internally,


muxDevLoad( ) calls the driver’s endLoad( ) or nptLoad( ). After the device is
loaded, you must call muxDevStart( ) to start the device.
The pInitString argument passes almost directly into the endLoad( ) or nptLoad( )
routine. The only change being that muxDevLoad( ) prepends the unit number
and a colon (for example, “1:”) to the string.
Likewise, the pBSP argument is passed along to the driver, which may or may not
use it. This argument can be used to pass in tables of BSP-specific routines that the
driver can use.
void * muxDevLoad
(
int unit, /* unit number of device */
END_OBJ * (* endLoad)(char *, void *), /* driver's load function */
char * pInitString, /* init string for driver */
BOOL loaning, /* unused */
void * pBSP /* BSP-specific */
)

This routine returns a cookie that can be passed to muxDevStart( ), or NULL, if the
device could not be loaded, in which case errno is set to S_muxLib_LOAD_FAILED.

B.2.11 muxDevStart( )

Use muxDevStart( ) to start a device after you have successfully loaded the device
using muxDevLoad( ). Internally, muxDevStart( ) activates the network interfaces
for a device by calling the drivers endStart( ) routine.
STATUS muxDevStart
(
void * pCookie /* the cookie returned from muxDevLoad() */
)

The muxDevStart( ) routine returns OK, on success; ERROR, if the driver’s


endStart( ) routine fails; or ENETDOWN, if pCookie does not represent a valid
device.

583
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

B.2.12 muxDevStop( )

Use muxDevStop( ) to stop the specified driver. Internally, muxDevStop( ) calls


the endStop( ) or nptStop( ) routine registered for the driver.
STATUS muxDevStop
(
void * pCookie /* the cookie returned from muxDevLoad() */
)

The muxDevStart( ) routine returns OK, on success; ERROR, if the endStop( ) or


nptStop( ) routine registered for the driver fails; or ENETDOWN, if pCookie does not
represent a valid device.

B.2.13 muxDevUnload( )

Use muxDevUnload( ) to unload a device from the MUX. Unloading a device


closes any network connections made through the device.
To notify protocols that the device is unloading, muxDevUnload( ) calls the
stackShutdownRtn( ) routine for each protocol bound to the device (internally, the
stackShutdownRtn( ) should call muxUnbind( ) to detach from the device).
To free device-internal resources, muxDevUnload( ) calls the endUnload( ) or
nptUnload( ) routine that the device registered with the MUX.
STATUS muxDevUnload
(
char * pName, /* the name of the device, for example, ln or ei */
int unit /* the unit number */
)

This routine returns OK, on success; or ERROR, if the device could not be found, or
the error returned from the device’s endUnload( ) or nptUnload( ) routine if that
routine fails.

B.2.14 muxError( )

Drivers use muxError( ) to report an error to a network service that is bound to it


through the MUX. You can find predefined errors in end.h. This routine is passed
two arguments: the END object that identifies the device that is issuing the error
and a pointer to an END_ERR structure (see B.3.2 END_ERR, p.594).

584
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

void muxError
(
void * pEnd, /* END object pointer returned by end/nptLoad() */
END_ERR * pError /* error structure */
}

B.2.15 muxIoctl( )

Use muxIoctl( ) to access the ioctl services that network interfaces have registered
with the MUX. Typical uses of muxIoctl( ) include starting, stopping, or resetting
a network interface, or adding or configuring MAC and network addresses.
STATUS muxIoctl
(
void * pCookie, /* returned by muxTkBind() */
int cmd, /* ioctl command */
caddr_t data /* data needed to carry out the command */
)

This routine returns OK if successful; ERROR, if the device was unable to


successfully complete the command; or ENETDOWN, if the cookie did not
represent a valid device.

B.2.16 muxMCastAddrAdd( )

Use muxMCastAddrAdd( ) to add an address to the table of multicast addresses


maintained for a device. It expects two arguments: a cookie that was returned
when muxTkBind( ) was used to bind to the device, and a string containing the
address to be added.
STATUS muxMCastAddrAdd
(
void * pCookie, /* returned by muxTkBind() */
char * pAddress /* address to add to the table */
)

This routine returns OK, if successful; ERROR, if the device was unable to
successfully add the address (if this is because the device does not support
multicasting, errno will be set to ENOTSUP); or ENETDOWN, if the cookie does not
represent a valid device.
B

585
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

B.2.17 muxMCastAddrDel( )

Use muxMCastAddrDel( ) to remove an address from the table of multicast


addresses maintained for a device. It expects two arguments: a cookie that was
returned when muxTkBind( ) was used to bind to the device, and a string
containing the address to be removed.
STATUS muxMCastAddrDel
(
void * pCookie, /* returned by muxTkBind() */
char * pAddress /* address to delete from the table */
)

This routine returns OK, if successful. It returns ERROR if the device was unable to
successfully remove the address. If the failure is because the device does not
support multicasting, errno is set to ENOTSUP. If the failure was is because the
address was not found in the table, errno is set to EINVAL). The routine returns
ENETDOWN if the cookie does not represent a valid device.

B.2.18 muxMCastAddrGet( )

Use muxMCastAddrGet( ) to retrieve the list of multicast addresses that have been
registered for a driver. It expects two arguments: a cookie that was returned when
muxTkBind( ) was used to bind to the device, and a pointer to a pre-allocated
MULTI_TABLE structure into which the table contents will be written during this
routine call (see B.3.8 MULTI_TABLE, p.601).
int muxMCastAddrGet
(
void * pCookie, /* returned by muxTkBind() */
MULTI_TABLE * pTable /* structure that will hold retrieved table */
)

This routine returns OK, if successful; ERROR, if the device was unable to
successfully supply the list; or ENETDOWN, if the cookie does not represent a valid
device.

B.2.19 muxTkBind( )

Use muxTkBind( ) to bind a network service to a network interface. Before the


network service can send and receive packets from the network, it must bind to
one or more network drivers through which the packets will be sent and received.
To specify these network drivers and bind to them, use the routine muxTkBind( ).

586
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

In the call to muxTkBind( ) you must provide the following information:



the network driver to bind to (name and unit number)

a network service type, based on RFC 1700 or user-defined

optional data structures used to exchange information with the driver
(typically used when a network service is designed to work with a
particular network driver)
■ a set of callback routines used by the MUX (see Table B-1)
■ a key or private data structure that will be passed back when these
callbacks are invoked to identify the bound interface
These callback routines are listed in Table B-1 and are described at greater length
in 22.3.1 Service Routines Registered Using muxTkBind( ), p.517.

Table B-1 Network Service Callback Routines

Callback Routine Description

stackRcvRtn( ) Receive data from the MUX.

stackErrorRtn( ) Receive an error notification from the MUX.

stackShutdownRtn( ) Shut down the network service.

stackRestartRtn( ) Restart a suspended network service.

Two additional arguments (pNetSvcInfo and pNetDrvInfo) allow the sublayer to


exchange additional information with the network driver, depending on
requirements specific to the particular service or driver. The Wind River IP
network protocol, for instance, expects a driver to pass up certain information,
although it does not pass anything back down. These additional arguments may
be especially helpful to those network services and network driver types that are
naturally “tightly coupled.”
As part of the bind phase, the network service typically retrieves the address
resolution and mapping routines for each network interface that is being bound to,
storing them in a private data structure allocated by the service.
The muxTkBind( ) routine returns a cookie that uniquely represents the binding B
instance and is used to identify that binding instance in subsequent calls. A return
value of NULL indicates that the bind failed.

587
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The muxTkBind( ) routine is defined as:


void * muxTkBind
(
char * pName, /* interface name, for example: ln, ei */
int unit, /* unit number */
BOOL (* stackRcvRtn)(void *, long, M_BLK_ID, void *),
STATUS (* stackShutdownRtn)(void *),
STATUS (* stackRestartRtn)(void *),
void (* stackErrorRtn)(void *, END_ERR *),
long type, /* from RFC1700 or user-defined */
char * pProtoName, /* string name of service */
void * pNetCallBackId, /* returned to svc sublayer during recv */
void * pNetSvcInfo, /* ref to netSrvInfo structure */
void * pNetDrvInfo /* ref to netDrvInfo structure */
)

This routine returns a cookie that uniquely represents the binding instance, or
NULL if the bind fails.

NOTE: Although you can use muxTkBind( ) with both END and NPT devices, the
prototypes for the 4 registered routines differ as shown below.
END drivers:
BOOL (*stackRcvRtn) (void*, long, M_BLK_ID, LL_HDR_INFO *, void*),
STATUS (*stackShutdownRtn) (void*, void*),
STATUS (*stackTxRestartRtn) (void*, void*),
void (*stackErrorRtn) (END_OBJ*, END_ERR*, void*)

NPT devices:
BOOL (*stackRcvRtn) (void*,long, M_BLK_ID, void *),
STATUS (*stackShutdownRtn) (void *),
STATUS (*stackTxRestartRtn) (void *)
void (*stackErrorRtn) (void*, END_ERR*)

B.2.20 muxTkDrvCheck( )

A network service sublayer uses muxTkDrvCheck( ) to determine whether a


particular driver is an NPT driver.
int muxTkDrvCheck
(
char * pDevName /* the name of the device being checked */
)

This routine returns 1 if that device is an NPT driver, 0 (zero) otherwise, and
ERROR (-1) if the specified device could not be found.

588
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

NOTE: Internally, muxTkDrvCheck( ) uses an EIOCGNPT ioctl to ask the driver


whether its is an NPT. An NPT returns a zero in response to an EIOCGNPT ioctl.

B.2.21 muxTkPollReceive( )

A network service sublayer uses muxTkPollReceive( ) to poll a device for


incoming data. If no data is available at the time of the call, muxTkPollReceive( )
returns EAGAIN. The pSpare argument points to any optional spare data provided
by an NPT driver. In the case of an END, pSpare will always be NULL or point to
NULL.
STATUS muxTkPollReceive
(
void * pCookie, /* returned by muxTkBind() */
M_BLK_ID pNBuff, /* a vector of buffers passed to us */
void * pSpare /* a reference to spare data is returned here */
)

This routine returns OK on success; EAGAIN if no packet is available; ENETDOWN,


if the cookie passed in does not represent a loaded device; or an error value specific
to the end/nptpollReceive( ) routine registered for the particular driver.

NOTE: Poll mode should only be used for debugging. For details, see Polled Mode,
p.456.

NOTE: This routine replaces muxPollReceive( ), which has been deprecated for
future use.

B.2.22 muxTkPollSend( )

Use muxTkPollSend( ) to transmit packets when a driver is in polled-mode. This


is the polled-mode equivalent to the interrupt-mode muxTkSend( ). When using
muxTkPollSend( ), the driver does not need to call muxAddressForm( ) to
complete the packet, nor does it need to prepend an mBlk of type MF_IFADDR
containing the destination address. Like muxTkSend( ), this routine expects as
arguments a cookie identifying the device and a pointer to the mBlk chain B
containing the data.

NOTE: Poll mode should only be used for debugging. For details, see Polled Mode,
p.456.

589
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

STATUS muxTkPollSend
(
void * pCookie, /* returned by muxTkBind()*/
M_BLK_ID pNBuff, /* data to be sent */
char * dstMacAddr, /* destination MAC address */
USHORT netType, /* network service that is calling us */
void * pSpareData /* spare data passed to driver on each send */
)

This routine returns OK, on success; ENETDOWN, if the cookie passed in does not
represent a valid device; or an error value specific to the end/nptpollSend( ) routine
of the driver being used.

NOTE: This routine replaces muxPollSend( ), which has been deprecated for
future use.

B.2.23 muxTkReceive( )

A driver uses muxTkReceive( ) to pass validated packets up to the MUX.1


The muxTkReceive( ) routine forwards the data to the network service sublayer
by calling the stackRcvRtn( ) registered for that sublayer.
Arguments to the routine call include:

a reference to the END object returned by the endLoad( ) or nptLoad( ) routine

an mBlk or mBlk chain that contains the received frame

the offset value into the frame where the data field (the network service layer
header) begins

the network service type of the service for which the packet is destined2

a flag (wrongDstAddr) that should be set to TRUE if the packet being received
is not addressed to this device/service interface (which might happen if the
driver is in MUX_PROTO_PROMISC mode)

a reference to any optional data or information that a network service may
expect to accompany the packet

1. This routine is registered by the MUX as the receiveRtn in the END_OBJ data structure for
the device. The driver should make a call to this reference rather than calling
muxTkReceive( ) directly.
2. Typically, this value can be found in the header of the received frame.

590
B MUX/NPT Routines and Data Structures
B.2 MUX Routines

The MUX strips off the frame header before forwarding the packet to the network
service, unless the network service is registered as MUX_PROTO_SNARF or
MUX_PROTO_PROMISC, in which case it will receive the complete frame.
The routine is defined as:
STATUS muxTkReceive
(
END_OBJ * pEnd, /* returned by nptLoad() */
M_BLK_ID pMblk, /* the buffer being received */
long netSvcOffset, /* offset to network datagram in the packet */
long netSvcType, /* network service type */
BOOL wrongDstAddr, /* not addressed to this interface */
void * pSpareData /* out-of-band data */
)

This routine returns OK, on success; ERROR, if the cookie is invalid; or FALSE, if no
services are bound to the referenced driver.

B.2.24 muxTkSend( )

A network service sublayer uses muxTkSend( ) to transmit packets.


STATUS muxTkSend
(
void * pCookie, /* returned by muxTkBind()*/
M_BLK_ID pNBuff, /* data to be sent */
char * dstMacAddr, /* destination MAC address */
USHORT netType, /* network service that is calling us */
void * pSpareData /* spare data passed on each send */
)

To send a packet, the caller must supply:


■ the cookie obtained from bind that identifies the bound interface
■ a pointer to the buffer chain (mBlk chain) containing the packet
■ the physical layer address to which the packet is being sent
■ the type of network service that is sending the packet
The data to be sent should be formed into an mBlk chain (if it is not already in this
form). If the sublayer has a registered address resolution routine for the
service/device interface, it should call this routine to determine the destination
physical-layer address.
The muxTkSend( ) routine may return an error indicating that the driver is out of B
resources for transmitting the packet. You can use this error to establish a flow
control mechanism if desired. The sublayer typically waits to send any more
packets until the MUX calls the stackRestartRtn( ) callback routine.

591
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

This routine returns OK, if successful; END_ERR_BLOCK, if the send( ) routine of


the driver is temporarily unable to complete the send due to insufficient resources
or some other problem; ERROR, if the send( ) routine of the driver fails; or
ENETDOWN, if the cookie does not represent a valid device.

B.2.25 muxTxRestart( )

A network interface driver uses muxTxRestart( ) to tell a network service that it


may resume sending data. That network service is presumed to have paused itself
in response to an error returned from a muxTkSend( ) call. A driver can use
muxTxRestart( ) to implement flow control.
void muxTxRestart
(
END_OBJ * pEnd /* returned by endLoad() or nptLoad() */
)

B.2.26 muxUnbind( )

A network service uses muxUnbind( ) to disconnect from a device. As input,


muxUnbind( ) expects a cookie that identifies the device, the driver type that was
passed during the bind, and a pointer to the stack*RcvRtn( ) registered at
bind-time.
STATUS muxUnbind
(
void * pCookie, /* returned from muxTkBind() */
long type, /* the device type passed in at bind-time */
FUNCPTR stackRcvRtn /* pointer to the service receive routine */
)

This routine returns OK, if the device is successfully unbound; or ERROR


otherwise (if errno is set to EINVAL, the device was not bound to the service when
this routine was called).

592
B MUX/NPT Routines and Data Structures
B.3 Data Structures

B.3 Data Structures


This section provides descriptions for the following structures:

DEV_OBJ

END_ERR

END_OBJ

END_QUERY

LL_HDR_INFO

M2_INTERFACETBL

mBlk

MULTI_TABLE

NET_FUNCS

B.3.1 DEV_OBJ

The MUX uses the DEV_OBJ structure to store the name and control structure of
your device. The private control structure, held in the pDevice field of this
structure, stores information such as memory pool addresses and other essential
data. The DEV_OBJ structure is defined in end.h as:
typedef struct dev_obj
{
char name[END_NAME_MAX]; /* device name */
int unit; /* for multiple units */
char description[END_DESC_MAX]; /* text description */
void * pDevice; /* device control structure */
} DEV_OBJ;

name
A pointer to a string specifying the name of the network device.
unit
The unit number of the device. Unit numbers start at zero and increase for each
device controlled by the same driver.
description
A text description of the device driver. For example, the Lance Ethernet driver
uses the description string of “AMD 7990 Lance Ethernet Enhanced Network
Driver.” This string is displayed if muxShow( ) is called.
pDevice B
A pointer to the private control structure used by the device. A device can
access its own control structure by using the devObject.pDevice field of the
END_OBJ that the MUX passes into driver routines.

593
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

B.3.2 END_ERR

The END_ERR structure is defined as:


typedef struct end_err
{
INT32 errCode; /* Error code */
char * pMesg; /* NULL-terminated error message */
void * pSpare; /* Pointer to user-defined data */
} END_ERR;

The errCode field of the END_ERR structure is 32 bits long. The lower 16 bits are
reserved for system error messages, while the upper 16 bits may be used for
custom error messages. Table B-2 lists currently defined error codes:

Table B-2 END_ERR Error Codes

Error Code Description

END_ERR_INFO This error is informational only.


END_ERR_WARN A non-fatal error has occurred.
END_ERR_RESET An error occurred that forced the device to reset itself, but
the device has recovered.
END_ERR_FLAGS The driver has changed the flags field of the END_OBJ.

END_ERR_DOWN A fatal error occurred that forced the device to go down. The
device can no longer send or receive packets.

END_ERR_UP The device was down but has now come up and may again
send and receive packets.

B.3.3 END_OBJ

END_OBJ is the head of the structural interface between the MUX and a network
interface driver. The driver allocates this structure and initializes some of its
elements within its endLoad( ) or nptLoad( ) routine. The structure is defined in
target/h/end.h and is diagramed in Figure B-1.

594
B MUX/NPT Routines and Data Structures
B.3 Data Structures

Figure B-1 The END_OBJ Structure and Related Structures

END_OBJ
DEV_OBJ
node : NODE 1
pOutputFilterSpare : void * name : char[]
devObject unit : int
attached : BOOL description : char[]
txSem : SEM_ID pDevice : void *
flags : long
multiList : LIST
nMulti : int
protocols : LIST 1 NET_FUNCS
snarfCount : int pFuncTable start( )
pNetPool : NET_POOL_ID stop( )
receiveRtn( ) : STATUS unload( )
outputFilter( ) : BOOL ioctl( )
send( )
1 1
mCastAddrAdd( )
mib2Tbl pMib2Tbl
mCastAddrDel( )
(obsolete)
mCastAddrGet( )
M2_ID pollSend( )
pollRcv( )
formAddress( )
Manage the contents of the M2_ID structure packetDataGet( )
using the macros described in 21.4.4 MIB addrGet( )
endBind( )
Statistics Collection in END and NPT Drivers,

The MUX manages some of the elements in this structure, but the driver is
responsible for setting and managing others:
node
The root of the device hierarchy. The MUX sets the value of this field. The
driver should not modify the value of this item.
devObject
A pointer to the DEV_OBJ structure for this device (see B.3.1 DEV_OBJ, p.593).
The driver must set this value when its endLoad( ) or nptLoad( ) routine is
called.
receiveRtn
A function pointer that references a muxTkReceive( ) routine. The MUX
supplies this pointer when the driver is loaded. Any time after the completion B
of the muxDevLoad( ) call, the driver can use this receiveRtn( ) to pass data up
to the protocol layer.

595
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

The prototype for this receive routine is:


STATUS receiveRtn
(
void * pCookie, /* The cookie passed in to endLoad() */
M_BLK_ID pMblk /* The packet, as an mblk chain */
)

pSnarf, pTyped, pPromisc, pStop


These fields reference lists of protocols that have bound themselves to this
network driver. The MUX manages this list.
endStyle
Is this an END or NPT driver.
attached
A boolean indicating whether or not the device is attached. The MUX sets and
manages this value.
txSem
A semaphore that controls access to the device’s transmission facilities. The
MUX initializes txSem, but the driver gives and takes the semaphore as
needed.
flags
A value constructed by ORing combinations of the following flags:
IFF_ALLMULTI
This device receives all multicast packets.
IFF_BROADCAST
The broadcast address is valid.
IFF_DEBUG
Debugging is on.
IFF_LINK0
A per link layer defined bit.
IFF_LINK1
A per link layer defined bit.
IFF_LINK2
A per link layer defined bit.
IFF_LOOPBACK
This is a loopback net.
IFF_MULTICAST
The device supports multicast.

596
B MUX/NPT Routines and Data Structures
B.3 Data Structures

IFF_NOARP
There is no address resolution protocol.
IFF_NOTRAILERS
The device must avoid using trailers.
IFF_OACTIVE
Transmission in progress.
IFF_POINTOPOINT
The interface is a point-to-point link.
IFF_PROMISC
This device receives all packets.
IFF_RUNNING
The device has successfully allocated needed resources.
IFF_SIMPLEX
The device cannot hear its own transmissions.
IFF_UP
The interface driver is up.

! WARNING: If the driver changes the state of the flags element (for example,
marking itself as “down” by setting the IFF_DOWN flag), the driver should export
this change by calling muxError( ) with the errCode field of the END_ERR structure
set to END_ERR_FLAGS.

pFuncTable
A pointer to a NET_FUNCS structure (see B.3.9 NET_FUNCS, p.601). This
structure contains pointers to driver routines for handling standard requests
such as stop or send. Your driver must allocate and initialize this structure
when the endLoad( ) or nptLoad( ) routine is called.
mib2Tbl
An M2_INTERFACETBL structure used to track the MIB-II variables used in the
driver (see B.3.6 M2_INTERFACETBL, p.599). The driver should initialize this
structure, although the elements in the structure will be used and adjusted
both by the driver and by the MUX. For appropriate values for the elements in
this structure, see RFC 1158.
B
NOTE: Although mib2Tbl is still included and supported in this structure, it
is deprecated for future use. The maintenance of the interface group MIB
variables is now handled using an M2_ID structure, which is referenced using
the pMib2Tbl field of this structure.

597
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

multiList
A list of multicast addresses. The MUX sets and manages this list, but it uses
the driver’s nptMCastAddrAdd( ), nptMCastAddrDel( ), and
nptMCastAddrGet( ) to do so.
nMulti
The number of addresses on the list referenced by the multiList field described
above. The MUX sets this value using the information returned by the driver’s
nptMCastAddrGet( ) routine.
outputFilter
A function pointer that references an optional output filtering routine. This is
set by the MUX to the stackRcvRtn( ) of a network service that registers itself
as of the MUX_PROTO_OUTPUT type, if there is such a service.
pNetPool
A pointer to a netBufLib-managed memory pool. This pool, which is used
internally by the NPT, should be initialized in the endLoad( ) or nptLoad( )
routine.
pMib2Tbl
A pointer to an M2_ID structure, which is used to manage the interface group
MIB variables for this interface. You should only rarely need to access the
pMib2Tbl field, and you should never need to directly access the contents of
the M2_ID structure. Instead, you manage the interface group MIB variables
using macros that access function pointers registered with endLib. For more
information on these macros, see 21.4.4 MIB Statistics Collection in END and
NPT Drivers, p.465.

B.3.4 END_QUERY

This structure is designed specifically for use within the EIOCQUERY ioctl
command.
typedef struct
{
int query; /* the query*/
int queryLen; /* length of expected/returned data */
char queryData[4]; /* 4 byte minimum; 120 byte maximum */
} END_QUERY;

598
B MUX/NPT Routines and Data Structures
B.3 Data Structures

B.3.5 LL_HDR_INFO

The MUX uses the LL_HDR_INFO structure to keep track of link-level header
information associated with packets passed from an END to the MUX and from
there up to a protocol. An LL_HDR_INFO structure is passed as an argument to an
END’s stack receive routine.
The LL_HDR_INFO structure is defined as:
typedef struct llHdrInfo
{
int destAddrOffset; /* destination address offset into mBlk */
int destSize; /* size of destination address */
int srcAddrOffset; /* source address offset into mBlk */
int srcSize; /* size of source address */
int ctrlAddrOffset; /* control info offset into mBlk */
int ctrlSize; /* size of control info */
int pktType; /* type of the packet */
int dataOffset; /* offset into mBlk where data starts */
} LL_HDR_INFO;

B.3.6 M2_INTERFACETBL

The M2_INTERFACETBL structure is defined as follows (see also Figure B-1):


typedef struct
{
int ifIndex;
char ifDescr[M2DISPLAYSTRSIZE]; /* a text description. */
long ifType; /* type of device, from 1158. */
long ifMtu; /* maximum packet size. */
unsigned long ifSpeed; /* speed in bits/sec */
M2_PHYADDR ifPhysAddress; /* LLC address. */
long ifAdminStatus; /* UP/DOWN/TEST */
long ifOperStatus; /* UP/DOWN/TEST */
unsigned long ifLastChange; /* last change of the iface */
unsigned long ifInOctets; /* # of received octets */
unsigned long ifInUcastPkts; /* # of unicast packets received */
unsigned long ifInNUcastPkts; /* # of broad/multicast pkts recd */
unsigned long ifInDiscards; /* # of input dicards */
unsigned long ifInErrors; /* # of input errors */
unsigned long ifInUnknownProtos; /* # of unknown packets */
unsigned long ifOutOctets; /* # of octets sent */
unsigned long ifOutUcastPkts; /* # of unicast packets sent */
unsigned long ifOutNUcastPkts; /* # of broad/multicast pkts sent */
unsigned long ifOutDiscards; /* # of packets discarded */ B
unsigned long ifOutErrors; /* # of output errors */
unsigned long ifOutQLen; /* size of the output queue */
M2_OBJECTID ifSpecific; /* defs specific to media used */
} M2_INTERFACETBL;

599
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

NOTE: The M2_INTERFACETBL structure is deprecated for future use. For


information on the currently preferred mechanism for managing interface group
MIB variables, see 21.4.4 MIB Statistics Collection in END and NPT Drivers, p.465.

B.3.7 mBlk

Use mBlk structures as a vehicle for passing packets between the driver and
protocol layers. The mBlk structure is defined in netBufLib.h as:
typedef struct mBlk
{
M_BLK_HDR mBlkHdr; /* block header, pointer to mHdr structure */
M_PKT_HDR mBlkPktHdr; /* packet header, pointer to pktHdr structure */
CL_BLK * pClBlk; /* pointer to cluster block */
} M_BLK;

The elements of an mBlk structure are:


mBlkHdr
A pointer to an mHdr structure. If you chain this mBlk to another, you will
need to set the value of mBlkHdr.mNext or mBlkHdr.mNextPkt or both. The
mNext element is used to point to the next mBlk in a chain of mBlks, while the
mNextPkt element is used to point to an mBlk that contains the head of the
next packet.
mBlkPktHdr
A pointer to a pktHdr structure. Drivers attached to IP using ipAttach( ) must
set mBlkPktHdr.len so that the IP receive routine can locate the IP header.
pClBlk
A pointer to a clBlk structure. If you are using the netBufLib routines to
manage the driver’s memory pool, you will have no reason to access or modify
this field. If you are using your own driver memory pool management
routines, you will have to change the pClBlk.pClFreeRtn field to point to your
own memory free routine. This routine must use the same API as the
netBufLib free routine and you will have to update the pClBlk.pFreeArg1,
pClBlk.pFreeArg2, and pClBlk.pFreeArg3 members.
Setting appropriate values for the members of an mBlk structure and the
structures referenced by an mBlk structure is most easily accomplished by calling
the appropriate netBufLib routines for the creation of an mBlk/clBlk/cluster
construct.

600
B MUX/NPT Routines and Data Structures
B.3 Data Structures

B.3.8 MULTI_TABLE

The MULTI_TABLE structure is defined as follows:


typedef struct multi_table
{
long len; /* length of table, in bytes */
char * pTable; /* pointer to entries */
} MULTI_TABLE;

B.3.9 NET_FUNCS

The MUX uses this structure to reference the routines implemented for a driver.
The NET_FUNCS structure is defined as:
typedef struct net_funcs
{
STATUS (* start)(void *);
STATUS (* stop)(void *);
STATUS (* unload)(void *);
int (* ioctl)(void *, int, caddr_t);
STATUS (* send)(void *, M_BLK_ID);
STATUS (* mCastAddrAdd)(void *, char*);
STATUS (* mCastAddrDel)(void *, char*);
STATUS (* mCastAddrGet)(void *, MULTI_TABLE*);
STATUS (* pollSend)(void *, M_BLK_ID);
STATUS (* pollRcv)(void *, M_BLK_ID);
M_BLK_ID (* formAddress)(M_BLK_ID, M_BLK_ID, M_BLK_ID, BOOL );
STATUS (* packetDataGet)(M_BLK_ID, LL_HDR_INFO *);
STATUS (* addrGet)(M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID);
} NET_FUNCS;

The driver routines referred to in this structure are described in greater detail
elsewhere (see NPT Driver Entry Points Exported to the MUX, p.493 and END Entry
Points Exported to the MUX, p.478).

601
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

602
Index

Numerics Alternate Queueing Framework, component 408


ALTernate Queueing, see ALTQ
802.1Q VLAN ALTQ
chapter on 537 build components 407
management of 548 building for the network stack 406
MUX-L2 extensions for 541 CBQ bandwidth 402
non-Ethernet devices, and 544 CBQ priority 403
show routines for 558 compatibility with VxWorks 405
tag header 540 configuration parameters 408
configuration utility components 407
ECN 404
filter rules 421
A firewall and 419
machine clock 428
abbreviations, list of 573 overview 399
accept( ), accepting socket connection requests 248 priority queueing 401
accept_rtadv, IPv6 configuration parameter 65 priority queueing examples 424
accept_sourceroute, IP configuration parameter 52 RED 403
ACK delay, enabled, build-time configuration rules 419
parameter for 76 token bucket regulator 404
acronyms, list of 573 ALTQ_ MACH_CLOCK_ INIT_HOOK 409
address resolution, network services for 513 ALTQ_ MACH_CLOCK_ READ_HOOK 409
AF_INET ALTQ_DEFAULT_ QUEUE_LIMIT 408
binding to IPv4 address and port number 238 ALTQ_DEFAULT_ QUEUE_PRIORITY 408
specifying for communications domain 242 ALTQ_DISPATCH_ QUEUE_MAX_LEN 408
AF_INET 238, 242 ALTQ_MACH_ CLOCK_FREQ 408
AF_LOCAL 239 ALTQ_MAX_QUEUE_ ALLOWED 410
AF_ROUTE 239 ALTQ_USE_MACH_ CLOCK 410
albp, DHCP lease table parameter 197

603
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

altqConfig
CBQ and 422
B
examples 420 Berkeley Packet Filter (BPF)
overview 410 BPF devices,creating 453
RTPs and 405 header length, determining 454
show commands 426 type of link level frame, finding 454
always_keepalive, TCP run-time configuration binding names to sockets, bind( ) 244
parameter 58 BIOCSETF ioctl command 454
anonymous FTP 158 BIOCSETIF ioctl command 454
application protocols blackhole
configuring VxWorks for 146 TCP build-time configuration parameter 76
ARP TCP run-time configuration parameter 58
default table entries 342 UDP build-time configuration parameter 78
Ethernet configuration parameters 81 UDP run-time configuration parameter 62
ARP_DEBUG_CFG 345 blocking socket, avoiding 294
ARP_ENTRY_numbef_ADDR parameters 343 bmcastecho, ICMP, configuration parameter 51
ARP_ENTRY_number_HOST parameters 342 boot network interface, automatic stack attach 85
ARP_HOST_DOWN_TIME_CFG 81 BOOT_LINE_ADRS 186
ARP_MAX_AGE_CFG 81 BOOTP
ARP_MAX_ENTRIES_CFG 81 abbreviation for 573
ARP_MAXTRIES_CFG 81 compare with RARP 443
ARP_PROXYALL_CFG 81, 82 in an RTP 208
ARP_PRUNE_INTVL_CFG 81 BPF_BUFSIZE_CFG 453
ARP_REGISTER_CFG 345 BPF_HLEN 454
ARP_USELOOPBACK_CFG 81 BPF_TYPE 454
arpAdd( ), creating default and permanent ARP bpfDevCreate( ) 453
table entries 342 bpfDrv( ) 453
arpLib, configuration component 342 broadcasting
assoc_rtx_max, SCTP configuration parameter 57 IP, configuring addresses 439
attaching a stack to a network interface RIP, using 327
overview of 433 BSD drivers
automatic, boot interface, IPv4 85 entry points, implementing 504
automatic, boot interface, IPv6 16, 90 porting to MUX 504
explicitly, manually started interfaces 432 bsdSockLib 236
INCLUDE_IPATTACH 16 bucketlimit, TCP syncache configuration
AUTH_UNIX (RPC) 135 parameter 62
authentication, NFS 135 buffer alignment in network interface drivers 470
auto_asconf, SCTP configuration parameter 56 buffers, manipulation macros for 47
auto_flowlabel, IPv6 configuration parameter 65
setting default value at build time 88
auto_linklocal, IPv6 configuration parameter 65
setting default value at build time 89 C
cached routes, IPv6, maximum 89
cachelimit, TCP syncache configuration
parameter 62

604
Index

Carrier Sense Multiple Access with Collision configNet.h


Detection (CSMA/CD) 20 ENDs, adding 474
CBQ (class-based queueing) NPT drivers, adding 490
altqConfig and 422 connect( )
bandwidth 402 datagram sockets 249
filter rules 423 streams sockets 248
interface 402 connectivity, network
overview 401 testing under IPv4 23
priority 403 testing under IPv6 25
check_interface count, TCP syncache configuration parameter 62
build-time configuration parameter 80
run-time IPv4 configuration parameter 52
checksum, UDP
build-time configuration parameter 77 D
run-time configuration parameter 62
DAD packets 88
CL_DESC structure
dad_count, IPv6 run-time configuration
defined 33
parameter 65
tables of 45
data link layer
Class-Based Queueing, component 407
defined 568
class-based queueing, see CBQ
data pool
clBlk structures, user-defined memory pools, in 40
configuring 28
clid, DHCP lease table parameter 197
number of clBlk structures in 38
CLNT_TBL_SZ_CFG 344
number of mBlk structures in 38
cloned route expiration time, IPv6 89
per-size count of buffers in 38
close( ), sockets 251
storage buffers
clusters
allocating memory for 39
definition of 40
location in memory 38
sizes, setting 46
datagram
storing data in 46
defined 568
CMSG_DATA( ) 251
datagram size
CMSG_FIRSTHDR( ) 251
IP, raw, outgoing, maximum size 83
CMSG_NXTHDR( ) 251
UDP, incoming, maximum 78
cmsghdr structures, sockets 250
UDP, outgoing, maximum 78
code examples
datagram sockets
RIP route hook function 336
code examples
sockets, using
client-server communication 256
datagram 256
multicasting 261
multicasting (datagram) 261
multicasting 260
stream 266
using 255
zbuf sockets
datalink-MUX interface 461
display routine 285
debug log message, IPv6 87
TCP server, converting a 287
Default Queue Limit parameter 408 Index
communications domains, sockets 238
Default Queue Priority parameter 408
COMP protocol
default route, adding to route table 438
defined 568

605
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

defmcasthlim, IPv6 configuration parameter 65 DHCP6R_PRIORITY 205


setting default at build time 88 DHCP6R_SERVER_ADDR 205
delacktime, TCP configuration parameter 58 DHCP6R_SIZE 205
setting default at build time 75 DHCP6R_SRC_ADDR 205
delayed_ack, TCP configuration parameter 58 DHCP6R_UPLINK_IF 205
setting default value at build time 76 DHCP6R_UPORT 205
delayed_sack_time, SCTP configuration DHCP6R_VERBOSE 205
parameter 56 dhcp6relay 204
DEV_OBJ structure 593 DHCP6S_CONF_FILE_NAME 203
-DFASTUDP option DHCP6S_DOWNLINK_IF 204
building source for Fast UDP 274 DHCP6S_DPORT 203
DHCP (Dynamic Host Configuration Protocol) 181 DHCP6S_PRIORITY 204
see also BOOTP and RFC 1541 DHCP6S_RAMDISK_SIZE 204
see online dhcpcLib DHCP6S_SIZE 204
addresses, storing 198 DHCP6S_UPORT 203
applications, using in 190 DHCP6S_VERBOSE 204
DHCP v6 DHCPC_CPORT 185
relay agent 204 DHCPC_CPORT
run-time client 201 run-time client 183
server 203 DHCPC_DEFAULT_LEASE 185
IP address, changing target’s 190 DHCPC_DEFAULT_LEASE
lease table parameters 197 run-time client 183
leases DHCPC_DISCOVER_RETRIES
IP addresses and other parameters 189 run-time client 184
storing 198 DHCPC_MAX_LEASES 184
server, supported DHCPC_MAX_MSGSIZE 185
configuration component for 188 DHCPC_MAX_MSGSIZE
lease table configuration 196 run-time client 184
relay agent table configuration 198 DHCPC_MIN_LEASE 185
storage hook for 198 DHCPC_MIN_LEASE
DHCP_MAX_HOPS 188 run-time client 184
dhcp6c 201 DHCPC_OFFER_TIMEOUT 185
DHCP6C_DOWNLINK_IF 202 DHCPC_OFFER_TIMEOUT
DHCP6C_DPORT 202 run-time client 184
dhcp6c_ia 201 DHCPC_SPORT 185
DHCP6C_OPT_SEND_IA_ID 202 DHCPC_SPORT
DHCP6C_OPTION 202 run-time client 184
DHCP6C_PRIORITY 202 dhcpcBind( ) 190
DHCP6C_SIZE 202 dhcpcCommonLib, configuration component 186
DHCP6C_UPLINK_IF 202 dhcpcInit( ) 190
DHCP6C_UPORT 202 dhcpcOptionAdd( ) 190
DHCP6C_VERBOSE 202 dhcpcOptionGet( ) 191
DHCP6R_DOWNLINK_IF 205 dhcpcOptionSet( ) 190
DHCP6R_DPORT 205 dhcpcParamsGet( ) 192
DHCP6R_HOP_LIMIT 204 dhcpInformGet( ) 192

606
Index

dhcpOptionGet( ) 191 drop_redirect, ICMP configuration parameter 51


dhcprLib, configuration component 187 setting value at build time 84
dhcprTargetTbl structure 192 drop_synfin, TCP configuration parameter 58
DHCPS_ADDRESS_HOOK configuration DROUTER_STACK 234
parameter 189
DHCPS_ADDRESS_HOOK, synopsis for referenced
function 199
DHCPS_CPORT 188 E
DHCPS_DEFAULT_LEASE 189
EAGAIN 589
DHCPS_LEASE_HOOK
EALREADY 248
configuration parameter 189
ECN (Explicit Congestion Notification)
DHCPS_LEASE_HOOK, synopsis for referenced
ALTQ and 404
function 198
RED and 404
DHCPS_MAX_MSGSIZE 187
ecn_enable
DHCPS_SPORT 188
SCTP configuration parameter 56
DHCPS_STORAGE_CLEAR 200
ecn_nonce
DHCPS_STORAGE_READ 200
SCTP configuration parameter 56
DHCPS_STORAGE_START 199
egress filtering
DHCPS_STORAGE_STOP 199
defined 568
DHCPS_STORAGE_WRITE 199
EINPROGRESS 248
dhcpsLeaseEntryAdd( ) 195
EIOCGADDR
dhcpsLeaseTbl structure 196
endIoctl( ), and 488
dhcpsRelayTbl structure, relay agents and 198
nptIoctl( ), and 502
Dispatch Queue Max Length parameter 408
EIOCGFBUF
display routines, network interface information,
endIoctl( ), and 488
configuration component for 92
nptIoctl( ), and 502
DNS (Domain Name System)
EIOCGFLAGS
configuration component for 149
endIoctl( ), and 488
debug messages, enable display of 152
nptIoctl( ), and 502
overview 148
EIOCGHDRLEN
Resolver
endIoctl( ), and 488
in an RTP 209
nptIoctl( ), and 502
option flags 151
EIOCGMIB2
DNS_DEBUG, build-time configuration parameter
endIoctl( ), and 488
for turning on DNS debugging
nptIoctl( ), and 502
messages 152
EIOCGNPT 501
do_tcpdrain, TCP configuration parameter 58
EIOCMULTIADD
setting default value at build time 73
endIoctl( ), and 488
DO_TCPDRAIN_CFG 73
nptIoctl( ), and 502
domain name resolver
EIOCMULTIDEL
configuring for stack 150
endIoctl( ), and 488
Domain Name Server, specifying name of 150
nptIoctl( ), and 502 Index
domain value, routing socket 294
EIOCMULTIGET
domains, communications
endIoctl( ), and 488
for sockets 238
nptIoctl( ), and 502

607
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

EIOCPOLLSTART END_OBJ 594


nptIoctl( ), and 502 BSD drivers, and 504
EIOCPOLLSTOP ENDs, and 476
nptIoctl( ), and 502 NPT drivers, and 493
EIOCQUERY END_QUERY structure 598
endIoctl( ), and 488 bind calls, responding to 491
nptBind( ), and 491 nptIoctl( ), and 503
nptIoctl( ), and 502 endAddressForm( ) 485
EIOCSADDR endAddrGet( ) 486
endIoctl( ), and 488 endDevTbl[ ]
nptIoctl( ), and 502 ENDs, and 474
EIOCSFLAGS NPT drivers, and 490
endIoctl( ), and 488 endIoctl( ) 487
nptIoctl( ), and 502 endLib 457
EISCONN 248 endLoad( ) 479
END (Enhanced Network Driver) endMCastAddrAdd( ) 481
see also network interface drivers 473 endMCastAddrDel( ) 482
adding to an image 473 endMCastAddrGet( ) 482
compared to NPT drivers 462 endPacketDataGet( ) 486
data structures shared with MUX 477 endPollReceive( ) 483
entry points endPollSend( ) 483
compared with NPT driver 462 endSend( ) 481
list exported to MUX 478 endStart( ) 484
generic driver template for 473 endStop( ) 485
implementing 473 endUnLoad( ) 480
ioctl support 487 ENETDOWN
launching 475 muxPollReceive( ) 589
MUX interface 477 muxPollSend( ) 590
receiving frames 476 errCode 594
service bind event, response to 475 errppslimit, ICMPv6 parameter 63
END driver setting at build time 90
defined 569 etherMultiLib, configuration component 15
END_ERR structure 594 Ethernet link-layer run-time configuration
END_ERR_BLOCK parameters 69
muxTkSend( ), and 516 expiration time, cloned route, IPv6 89
nptSend( ), and 498 Explicit Congestion Notification, see ECN
END_ERR_DOWN error code 594 extension headers, maximum allowed per IPv6
END_ERR_FLAGS error code 594 packet 88
END_ERR_INFO error code 594
END_ERR_RESET error code 594
END_ERR_UP error code 594
END_ERR_WARN error code 594

608
Index

F FF_IFADDR_ADD 371
FF_IFADDR_DELETE 372
fast IP-forwarding applications 351 FF_IPV4_FIB_DISP_TBL 353
cache maintenance 360 FF_IPV4_INIT_RTN 353
entry points for, writing 363 FF_IPV6_FIB_DISP_TBL 353
xxCacheFlush( ) 372 FF_IPV6_INIT_RTN 353
xxCacheLookup( ) 374 ffCacheFlush 372
xxCacheWalk( ) 373 ffCacheWalk 373
xxInterfaceModeChanged( ) 370 ffInterfaceModeChanged 370
xxInterfaceStatusChanged( ) 371 ffInterfaceStatusChanged 371
xxMacEntryDeleted( ) 369 ffLibObjInit( ) 359
xxModeChanged( ) 371 ffLibUpdateStats( ) 365
xxPktSend( ) 365 ffMacEntryDeleted 369
xxRouteAdded( ) 366 ffModeChanged 371
xxRouteDeleted( ) 367 ffPktSend 365
xxRouteModified( ) 367 ffRouteAdded 366
xxRouteMoreInfo( ) 368 ffRouteDemoted 369
xxShutDown( ) 365 ffRouteModified 367
xxinit( ) 357 ffRouteMoreInfo 368
initializing 357 ffShutDown 365
populating cache for 360 File Transfer Protocol
registration with fastPathLib 359 Client IPv4, configuration of 156
supporting system management functions Client IPv6, configuration of 159
in 361 login security, configuration of 158
fast path Server IPv6, configuration of 160
defined 568 filter rules, ALTQ and 421
Fast UDP FIONBIO 294
building source for, -FASTUDP option 274 firewall
configuring VxWorks for 274 defined 568
writing socket applications 274 Firewall IP Filter, required by ALTQ 406
fastforwarding, IP parameter Firewall, required by ALTQ 400
setting at run-time 53 first, IP portrange parameter 54
fastforwarding,IP parameter flight size, slow start 61
setting at build time 82 setting at build time 76
FASTFORWARDING_CFG 82 flooding algorithm interval, ARP 68
fastPathLib 352 setting at build time 81
FASTUDP_DEBUG_CFG 275 flow control 516
FASTUDP6_DEBUG_CFG 275 folders, network component 14
fastUdp6Lib 275 forwarding
fastUdpLib 274 IP parameter 53
features in Platforms, see Wind River Platforms IPv4, enabling at build-time 79
FF_IF_ADD 372 IPv6, enabling at build time 87
Index
FF_IF_DELETE 372 IPv6, enabling at run time 66
FF_IF_DOWN 372 source-routed packets, enable at build time 80
FF_IF_UP 372

609
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

FTP (File Transfer Protocol)


file permissions 177
H
network devices, creating 178 hashsize, TCP syncache configuration
user ID, setting 177 parameter 62
FTP client hdrnestlimit, IPv6 parameter 66
in an RTP 209 heartbeat_interval, SCTP configuration
FTP server parameter 56
in an RTP 209 HFSC, not supported for ALTQ 401
FTP, anonymous 158 Hierarchical Fair Service Curve, see HFSC
FTP_DEBUG_OPTIONS 156 hifirst, IP port range parameter 54
FTP_TIMEOUT 158 setting at build time 79
FTP_TRANSIENT_FATAL 157 hilast, IP port range parameter 54
FTP_TRANSIENT_MAX_RETRY_COUNT 156 setting at build time 79
FTP_TRANSIENT_RETRY_INTERVAL 157 hlim, IPv6 parameter 66
ftp6Lib, configuration component 159 setting at build time 87
FTPD6_LOGINRTN 160 hop limit
FTPD6_OPTIONS_STRING 160 gif-encapsulated packet, for 88
FTPD6_SSIZE 160 IPv6 default 87
ftpd6Lib, configuration component 160 IPv6 multicasting default 88
ftpLib, configuration component 156 HOPCNT_INFINITY 334
FW_FIELD_ALTQ 419 host name
fwLib.h, ALTQ and 419 assigning to an address 439
fwRuleFieldSet 419 host route, adding to route table 437
host_down_time, link layer Ethernet parameter 68
setting at build time 81
G hostAdd( )
assigning a host name to an address 439
Gary Wright 3 remote file systems and 135
General Timer Facility hostent structure (DNS) 148
starting, build-time configuration 15 hosts.equiv 164
gif devices 444 hostShow 92
gif interface
defined 569
gifhlim, IPv6 hop limit for gif-encapsulated
packets 66
I
setting at build time 88 iam( ) 177
global variables, localized for multiple TCP/IP stack IANA, port assignments 245
instances 115 ICMP redirect, and RIP 335
glossary of terms 567 ICMP v6 configuration component 89
gratuituous_arp, link layer Ethernet parameter 68 icmp, ICMP run-time configuration parameters 52
GROUP_EXPORTS 133 ICMP_DROP_REDIRECT_CFG 83
ICMP_LOG_REDIRECT_CFG 84
icmp_may_rst, TCP parameter 58
setting at build time 84
ICMP_MAY_RST_CFG 84

610
Index

icmp6, ICMPv6 run-time configuration in.h 243


parameters 64 in_addr_t 246
ICMPBMCASTECHO_CFG 84 in_localaddr
icmpErrorLen, ICMP parameter 51 run-time parameter 54
setting at build time 84 setting at build time 80
ICMPERRORLEN_CFG 84 INCLUDE_ ALTQ_CBQ 407
icmpLib 16, 83 INCLUDE_ ALTQ_CONFIG 407
icmplim, ICMP parameter 52 INCLUDE_ ALTQ_PRIORITYQ 407
setting at build time 84 INCLUDE_ ALTQ_RED 407
ICMPLIM_CFG 84 INCLUDE_ ALTQ_RIO 407
icmplim_output, ICMP parameter 52 INCLUDE_ALTQ 407
ICMPMASKREPL_CFG 83 INCLUDE_ALTQ_RED 407
icmpShow, configuration component 92 INCLUDE_ALTQ_RIO 407
ICMPv4 configuration parameters INCLUDE_ARP_API 342
build time 83 INCLUDE_BOOT_LINE_INIT 18
run time 52 INCLUDE_BPF 453
ICMPv6 configuration parameters INCLUDE_BSD_SOCKET 15
build time 89 INCLUDE_DHCP_CORE 189
run time 64 INCLUDE_DHCP6C 201
ICMPV6CTL_ERRPPSLIMIT_CFG 90 INCLUDE_DHCP6R 204
ICMPV6CTL_MLD_MAXSRCFILTER_CFG 395 INCLUDE_DHCP6S 203
ICMPV6CTL_MLD_SOMAXSRC_CFG 395 INCLUDE_DHCPC_LEASE_SAVE 186
ICMPV6CTL_MLD_VERSION_CFG 396 INCLUDE_DHCPC_LEASE_TEST 186
ICMPV6CTL_NODEINFO_CFG 90 INCLUDE_DHCPC_SHARE 186
ICMPV6CTL_REDIRACCEPT_CFG 89 INCLUDE_DHCPS 188
ICMPV6CTL_REDIRTIMEOUT_CFG 89 INCLUDE_DNS_RESOLVER
if_msghdr structure 296, 297 including 149
ifAddrSet( ), using 435 modifying default values 21
ifBroadcastSet( ) 439 INCLUDE_DNS_RESOLVER 149
ifconfig( ), using 434 INCLUDE_EL3C90XEND 21
IFF_INET6_UP_CFG 90 INCLUDE_END 457
IFF_MULTICAST flag 260 INCLUDE_ETHERNET
ifm_msghdr structure 295 required for basic stack 15
ifMaskSet( ), using 435 required for MUXL2 539
ifShow 92 INCLUDE_FEI82557END 21
IGMP, show statistics for INCLUDE_FIREWALL_IP_FILTER, required by
build-time configuration component 92 ALTQ 400
igmpInterfaceDisable( ) 381 INCLUDE_FTP6 159
igmpInterfaceEnable( ) 381 INCLUDE_FTP6_SERVER 160
igmpLib 378 INCLUDE_FTPD6_SECURITY 158
igmpRouterLib 380 INCLUDE_GTF 15
igmpRouterLibInit( ) 380 INCLUDE_GTF_TIMER_START 15
Index
igmpRouterLibQuit( ) 381 INCLUDE_ICMP_SHOW 92
igmpShow 92 INCLUDE_ICMPV4 83
IGMPV3 378 INCLUDE_ICMPV6 89

611
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

INCLUDE_IGMP_ROUTER 380 INCLUDE_PROXY_SERVER 343


INCLUDE_IGMP_SHOW 92 INCLUDE_RARP 442
INCLUDE_INETLIB 16 INCLUDE_RAWV4 83
INCLUDE_IP6ATTACH 90 INCLUDE_RAWV6 89
INCLUDE_IPATTACH 85 INCLUDE_RCP 166
INCLUDE_IPV4 78 INCLUDE_REMLIB 164
INCLUDE_IPV6 86 INCLUDE_RIP 327
INCLUDE_L2CONFIG 540 INCLUDE_RIPNG 338
INCLUDE_L2CONFIG 540 INCLUDE_RLOGIN 167
INCLUDE_LINKBUFPOOL 29 INCLUDE_ROUTING_SOCKET 276
INCLUDE_MIB2_IF 466 INCLUDE_SC_SOCKLIB 236
INCLUDE_MIILIB 20 INCLUDE_SNTPC 152
INCLUDE_MLD 395 INCLUDE_SOCK_ZBUF 286
INCLUDE_MLD6_ROUTER 396 INCLUDE_SOCKLIB 235
INCLUDE_MROUTE 378 INCLUDE_SUBNET_VLAN 540
INCLUDE_MUX 457 INCLUDE_TCP_DEBUG 77
INCLUDE_MUX_L2 539 INCLUDE_TCP_SHOW 91
INCLUDE_NBIO_LOG 18 INCLUDE_TCPV4 73
INCLUDE_NDP 347 INCLUDE_TCPV6 86
INCLUDE_NET_BOOT 18 INCLUDE_TELNET 169
INCLUDE_NET_BOOT_CONFIG 18 INCLUDE_TELNET_CLIENT 171
INCLUDE_NET_DAEMON INCLUDE_TFTP_CLIENT 161
configuring 21 INCLUDE_TFTP_SERVER 162
including 18 INCLUDE_UDP_SHOW 91
INCLUDE_NET_DRV 18 INCLUDE_UDPV4 77
INCLUDE_NET_HOST_SETUP 18 INCLUDE_UDPV6 86
INCLUDE_NET_HOST_SHOW 92 INCLUDE_VIRTUAL_STACK_DEBUG 115
INCLUDE_NET_IF_SHOW 92 INCLUDE_VIRTUAL_STACK_EXAMPLE 115
INCLUDE_NET_INIT 18 INCLUDE_VIRTUAL_STACK_OLD_INTERFACE
INCLUDE_NET_POOL 28 114
INCLUDE_NET_REM_IO 18 INCLUDE_VIRTUAL_STACK_SHOW_FUNCTIO
INCLUDE_NET_ROUTE_SHOW 325 NS 114
INCLUDE_NET_ROUTE_SHOW_NBIO 325 INCLUDE_XDR
INCLUDE_NET_ROUTE_SHOW_SNPRINTF 325 including 20
INCLUDE_NET_ROUTE_SHOW_UNBUF 325 RPC 166
INCLUDE_NET_SHOW 92 INCLUDE_XDR_BOOL_T 166
INCLUDE_NET_SYSCTL 19 INCLUDE_ZBUF_SOCK 276
INCLUDE_NETBUFPOOL 29 inetLib, configuration component 16
INCLUDE_NETMASK_GET 18 inetstatShow( ), dependency on
INCLUDE_NETSTAT_MROUTEV6 397 INCLUDE_TCP_SHOW 92
INCLUDE_NETWORK inflight_debug, TCP configuration parameter 58
required by INCLUDE_END 457 inflight_enable, TCP configuration parameter 59
required by INCLUDE_NET_INIT 18 inflight_max, TCP configuration parameter 59
INCLUDE_PING 147 inflight_min, TCP configuration parameter 59
INCLUDE_PING6 147

612
Index

ingress filtering IPPROTO_TCP 242


defined 569 IPPROTO_UDP 242
init_rto_max, SCTP configuration parameter 57 ipRouteLib 324
init_rtx_max, SCTP configuration parameter 57 IPSENDREDIRECTS_CFG 79
interface status change, RIP response to 332 IPSTEALTH_CFG 80
interface, network driver, including 20 IPv4
Internet addresses broadcasting 439
adding to the routing table 436 datagram, raw, maximum incoming size 83
broadcast addresses, configuring 439 datagram, raw, maximum outgoing size 83
correcting interface assignment errors 438 forwarding, flow-based, enabling, build-time
ioctl commands 585 configuration parameter 82
ioctl( ), setting socket options 243 hostname, assigning to address 439
iosDrvInstall( ) IPv4/IPv6 functionality, enabling for an
socket functions passed to 534 interface 440
usrSockLibInit( ), and 525 IPV4_RT_DISP_TBL 82, 323
iosFdNew( ) 531 IPv6
IP addresses, example 10 broadcasting 439
IP v6, configuration component 86 defined 569
IP_ACCEPTSOURCEROUTE_CFG 80 hostname, assigning an address to 439
IP_ADD_MEMBERSHIP 261 IPv6 only, configuring stack as 88
IP_CHECKINTERFACE_CFG 80 IPV6CTL_ACCEPT_RTADV_CFG 87
IP_DEFTTL_CFG 79 IPV6CTL_AUTO_FLOWLABEL_CFG 88
IP_DOSOURCEROUTE_CFG 80 IPV6CTL_AUTO_LINKLOCAL_CFG 89
IP_DROP_MEMBERSHIP 261 IPV6CTL_DAD_COUNT_CFG 88
IP_MULTICAST_IF 261 IPV6CTL_DEFHLIM_CFG 87
IP_MULTICAST_LOOP 261 IPV6CTL_DEFMCASTHLIM_CFG 88
IP_MULTICAST_TTL 261 IPV6CTL_FORWARDING_CFG 87
ip6, IPv6 parameters 65 IPV6CTL_GIF_HLIM_CFG 88
ip6_mcast_pmtu, IPv6 parameter 66 IPV6CTL_KEEPFAITH_CFG 87
ipAttach( ) 121 IPV6CTL_MAXFRAGPACKETS_CFG 87
ipc, parameters for IP connections 50 IPV6CTL_RR_PRUNE_CFG 88
IPFORWARDING_CFG 79 IPV6CTL_RTEXPIRE_CFG 89
ipport_firstauto 54 IPV6CTL_RTMAXCACHE_CFG 89
ipport_hifirstauto 54 IPV6CTL_RTMINEXPIRE_CFG 89
IPPORT_HIFIRSTAUTO_CFG 79 IPV6CTL_SENDREDIRECTS_CFG 87
ipport_hilastauto 54 IPV6CTL_USE_DEPRECATED_CFG 88
IPPORT_HILASTAUTO_CFG 79 IPV6CTL_V6ONLY_CFG 88
ipport_lastauto 54 isn_reseed_interval, TCP configuration
ipport_lowfirstauto 55 parameter 59
ipport_lowlastauto 55
IPPORT_RESERVED_CFG 79
IPPORT_RESERVEDSTART_CFG 79
Index
IPPORT_USERRESERVED_CFG 79
IPPROTO_ICMP 243
IPPROTO_IP 243

613
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

J LOAD_STRING
ENDS, adding 474
jumbogram NPT drivers, adding 490
defined 569 local domain sockets, working with 240
overview 71 including in an image 241
setting up 241
local_slowstart_flightsize, TCP parameter 59
setting at build time 76
K log_arp_wrong_iface, link layer Ethernet
parameter 68
keepalive: idle, see keepidle setting at build time 82
keepalive: interval, see keepintvl LOG_ARP_WRONG_IFACE_CFG 82
keepfaith log_in_vain
IPv6 parameter 66 TCP parameter 60
setting at build time 87 setting at build time 75
keepidle UDP parameter 62
TCP parameter 59 setting at build time 77
setting at build time 74 log_interval, IPv6 parameter 66
keepinit, TCP parameter 59 log_redirect, ICMP parameter 52
keepintvl, TCP parameter 59 setting at build time 84
setting at build time 75 LOGIN_PASSWORD 171
kern, run-time configuration parameters 50 LOGIN_USERNAME 171
loginLib 171
loopback driver for local traffic, ARP 81
loopback_nocsum, SCTP configuration
L parameter 56
lowfirst, also known as ipport_lowfirstauto 55
last
build time value derived from
IP port range parameter, ipport_lastauto 54
IPPORT_RESERVED_CFG
last, IP port range parameter, ipport_lastauto
lowlast
setting at build time, reserved first port 79
also known as ipport_lowlastauto 55
link layer Ethernet run-time configuration
setting at build time 79
parameters 69
link layer functionality, enabling for an
interface 440
linkBufPool 29 M
link-level header
muxTkSend( ), and 591 M_BCAST
nptSend( ), and 497 NPT drivers, and 492
link-local address, IPv6, automatic assigning 89 M_CL_CONFIG
listen( ), listening for socket connection defined 32
requests 248 mapping to system and data pool
LL_HDR_INFO data structure 599 parameters 32
LOAD_FUNC setting up a memory pool 45
ENDs, adding 474 M_LEADINGSPACE( ) 48
NPT drivers, adding 490

614
Index

M_MCAST maxl, DHCP lease table parameter 197


NPT drivers, and 492 maxsockbuf, IP connections parameter 50
M_PREPEND( ) 47 MAXSOCKBUF_CFG 236
M2_INTERFACETBL, obsolete structure maxtries, link layer Ethernet parameter 69
listing of 599 setting at build time 81
m2IfInit( ) 466 mBlk structures
m2IfLib, configuration component for 466 field descriptions 600
m2Rip( ) 330 memory pools, in
MAC user-defined 40
defined 569 MCAST_BLOCK_SOURCE 379
MAC interface MCAST_JOIN_SOURCE_GROUP 379
defined 569 MCAST_LEAVE_GROUP 379
machine clock, ALTQ and 428 MCAST_LEAVE_SOURCE_GROUP 379
Machine-clock frequency parameter 408 MCAST_UNBLOCK_SOURCE 379
Machine-clock init routine parameter 409 Media Independent Interface (MII) library, see
Machine-clock init routine, sample code 428 INCLUDE_MIILIB
Machine-clock read routine parameter 409 memory leaks, avoiding 509
Machine-clock read routine, sample code 428 memory pools
Mark A. Miller 4 see online netBufLib
maskrepl, ICMP run-time configuration usage, estimating 30
parameters 52 user-defined 39
max_age, link layer Ethernet parameter 69 buffer manipulation macros 47
setting at build time 81 CL_DESC tables, preparing 45
max_hdr, parameter for IP connections 50 cluster sizes, valid 46
max_linkhdr, IP connection parameter 50 M_CL_CONFIG tables, preparing 45
MAX_LINKHDR_CFG 465 organizing 40
max_protohdr, IP connections parameter 50 setting up 45
maxburst, SCTP configuration parameter 56 storing data in 46
maxchunks, SCTP configuration parameter 56 memShow( ) 31
maxdgram, configuration parameter MF_IFADDR 589
raw IP 55 MIB II table, loading the (NPT drivers) 495
setting at build time 83 MIB2IF_LONG_COUNTERS 466
UDP 63 MIB2IF_TRAP_ARG 466
setting at build time 78 MIB2IF_TRAP_RTN 466
maxdgram, SCTP configuration parameter 55 MII interface to PHY
maxfragfragsperpacket, configuration parameter providing Ethernet drivers with 20
IPv4 53 MII-compliant interface 20
maxfragpackets, configuration parameter MLD
IPv4 53 defined 570
IPv6 66 host support 395
setting at build time 87 relay router 396
Maximum Number ALTQ Queues parameter 410 mldLib 395
Index
Maximum Segment Lifetime (TCP) 75 MLDV2 394
Maximum Segment Size, TCP, IPv4 73 mount1Lib 140
Maximum Segment Size, TCP, IPv6 86 mount3Lib 141

615
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

mounting file systems 134 muxAddrResFuncGet( )


MSG_MBUF, usrSockRecv( ), and 528 NPT drivers, and 464
msl, TCP configuration parameter 60 muxBind( )
setting at build time 75 parameter descriptions 582
mssdflt, TCP configuration parameter 60 service functions of 518
setting at build time 73 muxDevExists( ) 582
MTU Discovery, Path 76 muxDevLoad( ) 461
MULTI_TABLE structure 601 parameter descriptions 583
multicast group, join and leave options 379 muxDevStart( )
Multicast Listener Discovery, see MLD parameter descriptions 583
multicasting muxDevStop( ) 584
datagram sockets, using 260 muxDevUnload( )
code example 261 parameter descriptions 584
options 261 muxError( ) 584
RIP, using 327 muxIfFuncAdd( )
multiple network drivers, using parameter descriptions 579
run-time, configuring at 432 muxIfFuncDel( )
MUX parameter descriptions 580
API 577 muxIfFuncGet( )
configuration component for 457 parameter descriptions 581
datalink interface 461 muxIoctl( ) 585
defined 570 muxLib 457
END interface 477 muxMCastAddrAdd( ) 585
NPT driver interface 493 muxMCastAddrDel( ) 586
OSI model, and 458 muxMCastAddrGet( ) 586
overview 458 muxShow( )
protocol-MUX interface 460 multiple network drivers, starting 432
MUX_L2_MAX_VLANS_CFG 539 muxTkBind( )
MUX_L2_NUM_PORTS_CFG 539 parameter descriptions 586
MUX_PROTO_OUTPUT service functions of 517
bind phase, in 512 muxTkDrvCheck( ) 512
END_OBJ elements, and 598 parameter descriptions 588
MUX_PROTO_PROMISC muxTkLib 457
bind phase, in 512 muxTkPollReceive( ) 589
in muxTkReceive( ) discussion 591 muxTkReceive( )
MUX_PROTO_SNARF parameter descriptions 590
bind phase, in 512 muxTkSend( ) 514
in muxTkReceive( ) discussion 591 parameter descriptions 591
muxAddressForm( ) 581 muxTxRestart( ) 592
muxAddrResFuncAdd( ) muxUnbind( ) 460
multiple network drivers, starting 432 parameter description 592
NPT drivers, and 464
muxAddrResFuncDel( )
NPT drivers, and 464

616
Index

N netPoolCreate( ) 39
netPoolInit( ) 28
nd6_debug, ICMPv6 configuration parameter 63 mapping configuration parameters to elements
nd6_delay, ICMPv6 configuration parameter 63 in 32
nd6_drlist, ICMPv6 configuration parameter 63 netShow, configuration component 92
nd6_maxnudhint, ICMPv6 configuration netStackDataPoolShow( )
parameter 64 estimating memory pool usage 31
nd6_maxquelen, ICMPv6 configuration netStackSysPoolShow( )
parameter 64 estimating memory pool usage 31
nd6_mmaxtries, ICMPv6 configuration Network Buffer Library Additional Features
parameter 64 component 30
nd6_prlist, ICMPv6 configuration parameter 64 network connectivity, testing
nd6_prune, ICMPv6 configuration parameter 64 under IPv4 23
nd6_umaxtries, ICMPv6 configuration under IPv6 25
parameter 64 network information display routines, configuration
nd6_useloopback, ICMPv6 configuration component for 92
parameter 64 network interface configuration
Neighbor Discovery Protocol (NDP) 342 ifconfig( ), using 434
net.inet.icmp, ICMP parameters 52 ifMaskSet( ), ifAddrSet( ), using 435, 436
net.inet.ip, IPv4 parameters 52 network interface driver, including 20
net.inet.ip.portrange, IPv4 parameters 54, 55 network interface drivers
net.inet.raw, raw IP parameters 55 see also END (Enhanced Network Driver);
net.inet.sctp, SCTP parameters 55 Network Protocol Toolkit (NPT)
net.inet.tcp, TCP parameters 58 driver
net.inet.udp, UDP parameters 62 buffer alignment 470
net.inet6.icmp6, ICMPv6 parameters 64 link-level header allocation, early 465
net.inet6.ip6, IPv6 parameters 65 memory, managing 464
net.link.ether, link layer Ethernet parameters 69 multiple drivers, supporting 507
net.link.ether.inet parameters 68 scatter-gather, supporting 464
NET_FUNCS table network interfaces
filling 495 additional, starting at run-time 432
listing of 601 attaching to stack 433
NET_JOB_NUM_CFG 22 fixing IP address assignment errors 438
NET_TASK_OPTIONS 23 pausing 440
NET_TASK_PRIORITY 22 Network Protocol Toolkit (NPT) drivers
NET_TASK_STACKSIZE 23 see also network interface drivers
netBufLib 464 adding to an image 490
netDevCreate( ) 178 bind events, responding to 491
netDrv BSD drivers to, porting 504
downloading run-time images 178 compared to END drivers 462
general usage information 177 END_OBJ data structure 493
netJobAdd( ) entry points 462
Index
ENDs, and 476 exported to MUX 493
INCLUDE_NET_DAEMON 21 implementing 489
NPT drivers, and 492 ioctl support 501

617
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

launching 491 NFS2_CLIENT_CACHE_DEFAULT_LINE_SIZE 1


MUX interface 493 30
receiving frames 492 NFS2_CLIENT_CACHE_DEFAULT_NUM_LINES
network route, adding to route table 437 129
network services NFS2_CLIENT_CACHE_DEFAULT_OPTIONS 13
address resolution 513 0
binding 512 nfs2dLib 140
device control 516 nfs2Drv 129
driver paradigms, determining 512 nfs2Lib 129
errors, listening for 515 NFS3_CLIENT_CACHE_DEFAULT_LINE_SIZE 1
flow control 516 31
interface initialization 512 NFS3_CLIENT_CACHE_DEFAULT_NUM_LINES
ioctl commands for, defining 585 131
receiving packets 515 NFS3_CLIENT_CACHE_DEFAULT_OPTIONS 13
sending packets 514 2
shutting down an interface 515 nfs3dLib 141
socket interface, adding a 520 nfs3Drv 130
subroutines for 516 nfs3Lib 130
writing a sublayer 512 nfs3StableWriteGet( ) 132
network stack configuration nfs3StableWriteSet( ) 132
build time 14 nfsAuthUnixPrompt( ) 135
run-time 50 nfsAuthUnixSet( ) 135
NewReno Algorithms 77 nfsCommon 128
newreno, TCP configuration parameter 60 nfsExport( ) 141, 143
setting at build time 77 nfsMount( ) 135
NEXTADDR( ) sample macro 316 nfsMountAll( ) 133
NFS (Network File System) nodeinfo, ICMPv6 configuration parameter 64
authentication 135 setting at build time 90
client, target as 134 non-blocking socket 294
group IDs, setting 135 NPT driver
mounting file systems 134 defined 570
network devices, creating 135 NPT see Network Protocol Toolkit (NPT) 457
server nptBind( ) 496
setting up 143 nptIoctl( ) 501
user IDs, setting 135 nptLoad( ) 494
NFS server entry point of, specifying 490
reply cache 139 nptMCastAddrAdd( ) 498
NFS_GROUP_ID 135 nptMCastAddrDel( ) 498
core NFS client 128 nptMCastAddrGet( ) 499
NFS server 140 nptPollReceive( ) 500
NFS_MAXFILENAME 140 nptPollSend( ) 499
NFS_MAXPATH nptSend( ) 497
NFS core client 128 nptStart( ) 501
NFS server 140 nptStop( ) 501
NFS_USER_ID 128, 140 nptUnLoad( ) 496

618
Index

nr_outgoing_streams, SCTP configuration PHY (Physical Layer Entities)


parameter 57 initializing and configuring 21
NSCOUNT_CFG 151 MII compliancy 21
NUM_DAT_64 and all the other NUM_DAT_number MII-compliant interface 20
parameters 38 Physical Layer Entities, see PHY
NUM_DAT_CLBLKS 38 ping utility
NUM_DAT_MBLKS 38 in an RTP 210
NUM_SYS_16, and all the other NUM_SYS_number ping utility
parameters 37 network connections, testing 23
NUM_SYS_CLBLKS 36 suppressing printed output 24
NUM_SYS_MBLKS 35 PING_OPT_SILENT 24, 147
ping6( ) 25
configuration component 147
ping6Lib, configuration component 147
O pingLib, configuration component 147
Platforms for Consumer Devices, see Wind River
OSI network model
Platforms
defined 570
Platforms for Industrial Devices, see Wind River
Platforms
Platforms for Network Automotive Devices, see
P Wind River Platforms
Platforms for Network Equipment, see Wind River
packet Platforms
defined 570 PMA_DAT_64 and all the other PMA_DAT_number
packet filtering parameters 38
defined 570 PMA_SYS_16 and all the other PMA_SYS_number
passwd 135 parameters 37
password protection for Telnet and FTP, PMA_SYSPOOL 36
component 171 PMS_DAT_64 and all the other PMS_DAT_number
Path MTU Discovery 76 parameters 39
path_mtu_discovery, TCP parameter 60 PMS_SYS_16 and all the other PMS_SYS_number
setting at build time 76 parameters 37
path_rtx_max, SCTP configuration parameter 57 PMS_SYSPOOL 36
pausing, network interfaces 440 pmtu_raise_time, SCTP configuration
pcbcount, report of active PCBs 60 parameter 56
pcblist, list of active sockets polled-mode, NPT drivers, and 499
raw IP 55 port numbers
TCP 60 ephemeral 245
UDP 63 well-known and registered 245
pDst.mBlkHdr.reserved field 485 port unreachables for refused connects 78
peer_chkoh, SCTP configuration parameter 56 PORT_TBL_SZ_CFG 345
pending socket connection queue size priority inversion 22
Index
build-time configuration 236 priority queueing, ALTQ 401
run-time configuration 50 Priority Queueing, component 407
PF_ROUTE 294

619
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

protocol RDISC (ICMP Router Discovery) Server


defined 571 configuration and control of 348
protocol ID interface status change events 349
adding to a routing socket message 319 shutting down 349
extracting from a routing socket message 311, RDISC_OPTIONS 348
313 RDISC_PRIORITY 348
proxy ARP rdiscIfReset( ) 349
see also RFC 826; RFC 925; RFC 1027 rdiscLib 348
Proxy ARP, enable 82 rdiscLibInit( ) 348
PROXY_ARP_VERBOSE_CFG 345 read( ), sockets 249
PROXY_BROADCAST_FWD_CFG 345 reading, recommended 3
PROXY_BROADCAST_VERBOSE_CFG 345 reassembly queue, IPv6, maximum packets in
proxyall, link layer Ethernet parameter 69 queue 87
setting at build time 81, 82 recv( ) 249
proxyArpLib 343 recvfrom( ) 250
PROXYD_MAIN_ADDRESS 344 recvmsg( ) 250
PROXYD_PROXY_ADDRESS 344 recvspace incoming packet size
prune interval for ARP list 81 raw IP 55
prune_intvl, link layer Ethernet parameter 69 TCP 60
setting at build time 81 setting at build time 75
ptRibDispatchTable 82, 323 UDP 63
setting at build time 78
recvspace, raw IP parameter
setting at build time 83
Q recvspace, SCTP configuration parameter 55
RED (Random Early Detection)
QoS,ALTQ supporting 399
ALTQ and 403
Quality of Service, see QoS
build components 407
ECN and 404
RED with In and Out, component 407
R rediraccept, ICMPv6 parameter 64
setting at build time 89
Random Early Detection, see RED redirect cache time out, IPv6 90
RARP_DEBUG 443 redirect parameter, allow redirects
rarpDebugSet( ) 443 IPv4 53
rarpGet( ) 443 setting at build time 79
rarpLib 442 IPv6 67
raw sockets, IPv6 19 setting at build time 87
raw, raw IP run-time configuration parameters 55 redirtimeout, ICMPv6 parameter 65
RAW_MAXDGRAM_CFG 83 setting at build time 89
RAW_RECVSPACE_CFG 83 refused connections, black hole response
rcmd( ) default timeout for 164 TCP, RST 76
rdCtl( ) 348 UDP, port unreachables 78
registered port numbers 245

620
Index

remlib RFC 1058


in an RTP 210 RIP, older type message 211
remLib, associated configuration component 164 RIP, version 1.Wind River
remote file access implementation 326
overview of 146 RFC 1094
netDrv, using 176 NFS v2 server 140
permissions 177 RFC 1213
remLib configuration component 164 drivers 465
remote file system MIB interface structure, initializing 467
mounting 135 MIB-II table, retrieving 502
Remote Procedure Call (RPC) protocol, route, metrics for 307
configuration component 166 RFC 1256
RES_DEFAULT 151 solicitation and response, message format 348
RES_name, DNS Resolver option flags 151 RFC 1323
RES_OPTIONS_CFG 151 TCP extensions, enabling at build time 73
RES_TIMEOUT_CFG 150 TCP extensions, enabling at run time 61
resolver (DNS) RFC 1350
overview of 148 TFTP client, recommendations for packet
RESOLVER_DOMAIN 150 format 161
RESOLVER_DOMAIN_SERVER 150 TFTP server, recommendations for packet
resolvGetHostByAnyAddr( ) 148 format 162
resolvGetHostByName( ) 148 RFC 1388
resolvLib 149 RIP, version 2, with extensions 326
resolvParamsGet( ) 148 RFC 1389
resolvParamsSet( ) 148 RIP parameters to routines, described 330
restarting, network interfaces 440 RFC 1644
RETR command 176 TTCP extensions, enabling at build time 74
RETRY_CFG 151 TTCP extensions, enabling at run time 61
rexmit 60 RFC 1700
rexmit_min, TCP configuration parameter 60 obsolete 376
rexmit_slop, TCP configuration parameter 60 RFC 1769
rexmtlimit 62 SNTP client, default port value 153
rexmtlimit, TCP syncache configuration SNTP server, default port value 154
parameter 62 RFC 1813
RFC NFS v3 server, mount protocol 141
defined 571 supported client requests 142
RFC 1014 RFC 1831
XDR, routines 166 RPC protocol 165
RFC 1027 RFC 2080
proxy ARP, implementation described 344 RIPng, detailed description 338
RFC 1034 RIPng, Wind River implementation for
DNS 148 IPv6 326
Index
RFC 1035 RFC 2131
DNS 148 DHCP, implementing 181

621
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

RFC 2132 RFC 2893


DHCP server handling BOOTP requests 182 gif devices, style of configured tunnels 449
RFC 2233 gif tunnels 445
64-bit counters 466 RFC 2960
drivers 465 SCTP overview 93
MIB interface structures, initializing 467 SCTP, comparing with TCP and UDP 71
MIB structure, getting for END driver 488 RFC 3041
MIB structure, getting for NPT driver 502 temporary addresses, allow use of 68
RFC 2236 RFC 3232
IGMPv2 router, listening on interfaces 380 registered IPv4 multicast groups, list of 376
IGMPv2, implementation based on 378 RFC 3309
RFC 2375 SCTP CRC-32 checksum algorithm 94
IPv6 multicasting 377 RFC 3376
RFC 2452 IGMPv3, implementation based on 378
TCP MIBs 5 RFC 3493
RFC 2453 IPv6 multicasting 261
RIP implementation 326 socket extensions for IPv6 232
RFC 2454 RFC 3513
UDP MIBs 5 IPv6 addressing 72
RFC 246 IPv6 multicasting 377
END to IPv6, attaching 90 RFC 3542
RFC 2460 IPv6 multicasting 261
core IPv6 72 socket API for IPv6 232
RFC 2461 RFC 3596
NDP protocol 72 IPv6 records, DNS 148
RFC 2462 RFC 3678
IPv6 autoconfiguration functionality 200 MLDv2 socket options 396
section 5.5.4, configuration parameter 88 multicasting socket interface extensions 395
section 5.5.4, run-time variable 67 socket options 379
RFC 2463 RFC 3810
ICMP IPv6 implementation 72 MLDv2 host, implementing 395
RFC 2465 RFC 3873
IPv6 MIBs 5 SCTP MIB 95
RFC 2466 RFC 768
ICMPv6 MIBs 5 UDP 71
RFC 2674 RFC 792
VLAN, static objects 547 ICMP IPv4 implementation 72
RFC 2675 RFC 793
jumbogram, changes for 72 TCP 71
RFC 2710 RFC 826
MLDv1, implementing 395 ARP defined 342
RFC 2849 ARP protocol 344
test and documentation addresses 11 RFC 854
telnet 171

622
Index

RFC 894 route expiration time between 328


ethernet packet 470 version, setting 329
RFC 903 versions 327
RARP 442 RIP_AUTH_TYPE 329
RFC 925 RIP_EXPIRE_TIME 328
proxy ARP defined, VxWorks based on 344 RIP_GARBAGE_TIME 328
RFC information RIP_GATEWAY 328
SCTP, general 100 RIP_MULTICAST 328
rfc1323 RIP_REDIRECT_RECD 334
TCP parameter 61 RIP_ROUTE_CHANGE_RECD 334
rfc1323, TCP parameter RIP_SUPPLIER 329
setting at build time 73 RIP_SUPPLY_INTERVAL 329
rfc1644 RIP_TIMER_RATE 329
TCP parameter 61 RIP_VERSION 329
rfc1644, TCP configuration parameter ripAddrsXtract( ) 333
setting at build time 74 ripIfReset( ) 332
.rhosts 165 ripLib, configuration component for 327
Richard Stevens 3 RIPng
RIP (Routing Information Protocol) configuration component for 338
authentication type, configuring 329 priority of task, setting 339
broadcasting 327 RIPNG_OPTIONS_STRING 338, 339
debugging routines for 330 RIPNG_PRIORITY 339
garbage time for a route 328 ripRouteHookAdd( ) 333, 338
gateway, identifying self as 328 xxripRouteHookRtn( ) 333
ICMP redirect, responding to 335 ripRouteShow( ) 330
interface exclusion lists 331 rlogin client
interface status change, automatic response in an RTP 215
to 332 rlogin( ) 167
m2Rip( ) 330 rlogLib 167
multicast instead of broadcast 328 ROUNDUP( ) sample macro 312
multicasting 327 route change events and RIP 335
non-RIP routing events, monitoring 332 route table
non-RIP routing table event, responding editing, using routec( ) 436
to 334 ROUTE_DEFAULT_WEIGHT 324
route change event, responding to 335 ROUTE_SHOW_MEM 326
route hook function route6d 338
deleting 336 routec( )
sample function for 336 usage examples 437
run-time configuration 330 routed program 326
SNMP 330 router
subnet broadcasting 327 defined 571
table check interval 329 router advertisement
Index
updates messages, configuring acceptance of 87
allowing transmission of 329 router renumbering, walk timer, IPv6 88
interval, configuring 329 routeShow 325

623
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

routing socket RTM_NEWADDR 304


creating 294 RTM_NEWCHANGE 305
options, setting 294 RTM_NEWGET 306
routing socket messages RTM_NEWIPROUTE 308
accessing the addresses in 310 RTM_NEWMADDR 304
extracting information from 310 RTM_OLDIPROUTE 308
header structures for 295 RTM_REDIRECT 302
type values for 298 rtmaxcache
rpcTaskInit( ) 165 IP parameter 53
rr_prune, IPv6 parameter 67 setting at build time 80
setting at build time 88 IPv6 parameter 67
RSH (Remote Shell) setting at build time 89
file permissions 177 RTMAXCACHE_CFG 80
network devices, creating 178 rtminexpire
user ID, setting 177 IP parameter 53
RSH_STDERR_SETUP_TIMEOUT 164 setting at build time 80
rshd 176 IPv6 parameter 67
RST 76 setting at build time 89
rt_addrinfo structure 312 RTMINEXPIRE_CFG 80
rt_msghdr structure 295 rto_initial, SCTP configuration parameter 57
RT_PROTO_GET( ) 313 rto_max, SCTP configuration parameter 57
RT_PROTO_SET( ) 319 rto_min, SCTP configuration parameter 57
RTAX_MAX 312 RTP
rtexpire building 217
ICMPv6 parameter 67 in an RTP 210
setting at build time 89 initialization functions 222
IP parameter 53 launching 221
RTEXPIRE_CFG 80 network/RTP incompatibilities 215
RTF_name flags 308 overview 216
rti_info[ ] 312 shutting down 223
RTM_ADD 299 socket connections 223
RTM_ADDEXTRA 305 supported network applications 208
RTM_CHANGE 303 RTPs
RTM_DELADDR 304 altqConfig and 405
RTM_DELETE 300 rttdflt, TCP configuration parameter 61
RTM_DELEXTRA 305 rttimeout, IPv6 parameter 67
RTM_DELMADDR 304 RTV_name flags 318
RTM_GET 301 rules, ALTQ and 419
RTM_GETALL 306 run-time network stack configuration 50
RTM_IFANNOUNCE 305
RTM_IFINFO 304
RTM_LOCK 303
RTM_LOSING 302
RTM_MISS 303
rtm_name members of rt_msghdr structure 315

624
Index

S slowstart_flightsize, TCP parameter 61


setting at build time 76
-s “secure” option (TFTP) 162 SNARF
SACK defined 571
defined 571 SNMP (Simple Network Management Protocol)
SAL (Socket Application Library) 228 trap generator function, user-supplied 466
client 229 snmpMib2.mib 331
server 229 SNPTS_MODE 154
sample code, RIP route hook function 336 SNS (Socket Naming Service) 230
sb_efficiency value for sbreserve( ) calls 236 SNTP (Simple Network Time Protocol)
build time configuration 236 modes, server 153
run-time configuration 50 SNTP_ACTIVE 153
SB_MAX 236 SNTP_PASSIVE 153
scatter-gather support SNTP_PORT 154
introduced 464 SNTPC_PORT 153
buffer alignment, resolving 472 sntpcTimeGet( ) 153
SCTP SNTPS_DSTADDR 153
compiler option 95 SNTPS_INTERVAL 155
extended socket API for 102 SNTPS_MODE 153
monitoring, controlling 106 SNTPS_TIME_HOOK 155
status information 107 sntpsClockHook( ) 154
Stream Control Transmission Protocol, chapter sntpsClockSet( ) 154
on 93 sntpsConfigSet( ) 154
sctp, SCTP run-time configuration parameters 55 sntpsInit( ) 153
SCTP, Stream Control Transmission Protocol, SO_KEEPALIVE 75
chapter on 93 SO_LINGER 243
secret_lifetime, SCTP configuration parameter 57 SO_LINGER_INFINITE_CFG 237
security, TFTP 162 SO_REUSEADDR 243
send( ) 249 SO_USELOOPBACK 294
sendmsg( ) 250 SOCK_DGRAM 239
sendspace, TCP parameter 61 SOCK_FUNC 522
setting at build time 75 SOCK_RAW 294
sendto( ) 250 SOCK_SEQPACKET 240
setsockopt( ), setting socket options 243 SOCK_STREAM 240
shellParserControl, default command sockaddr_gate 307
interpreter 170 sockaddr_in, setup of 246
shutdown( ), sockets 251 sockaddr_in6, setup of 247
shutdown_guard_time, SCTP configuration sockbuf_waste_factor, IP connections
parameter 57 parameter 50
siad, DHCP lease table parameter 197 sockbuf_waste_factor, IP parameter
SIOCMSFILTER 379 setting at build time 236
SIZ_SYS_16, and all the other SIZ_SYS_number SOCKBUF_WASTE_FACTOR_CFG 236
Index
parameters 36 socket
slow start flight size 76 defined 571
Socket Application Library (SAL) 228

625
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

socket interface, standard, component for 235 VxWorks-specific issues 232


socket system call support component 236 zbuf sockets, advantages of 287
socket( ), creating a socket descriptor 242 sockets interface for a new network service
SOCKET_VLAN, compiler option 538 adding 520
sockets back end constant 522
accepting connections 248 functions 522
background reading 232 initialization function 522
binding a name to 244 SOCK_FUNC table 522
buffer size, maximum 236 sockLib 235
closing 251 sockLibAdd( ) 523
communications domains 238 sockScLib 236
configuration components for 235 SOL_SOCKET 244
connections usrGetSockOpt( ), and 532
creating 248 usrSetSockOpt( ), and 533
pending, queue size somaxconn, IP connections parameter 50
run-time configuration 50 SOMAXCONN_CFG 236
pending, queue size, build-time sourceroute, IP port range parameter 53
configuration 236 setting at build time 80
control information, accessing 250 source-routed IP packets, enabling forwarding 80
creating 242 spoofing
datagram defined 572
defined 239 stack global variables, localized 115
using 255 stack instances, multiple, TCP/IP
generic definition of 238 common object code base for 116
implicit bind( ) 245 selecting a stack instance 119
IP address convenience functions 253 showing stack information 119
IPv4 addresses, and 246 SNMP 122
IPv6 addresses, and 247 stack size for the FTP6 task 160
listening for connections 248 stackENDErrorRtn( ) 519
macros accessing control information 251 stackENDRcvRtn( ) 519
non-blocking 243 stackENDRestartRtn( ) 520
option values, retrieving 532 stackENDShutdownRtn( ) 519
options, setting 243 stackErrorRtn( ) 518
port numbers, ephemeral 245 stackRcvRtn( )
raw 240 synopsis for 517
raw, IPv4, basic networking support 19 stackRestartRtn( ) 518
raw, IPv4, component for 83 stackShutdownRtn( ) 517
sending/receiving data 249 stats
sockaddr_in, setup of 246 TCP, list statistics for 61
sockaddr_in6, setup of 247 UDP, list statistics for 63
stream stats, ICMP run-time configuration parameters 52
defined 240 stats, ICMPv6 configuration parameter 65
using 266 stats, IP portrange parameter 54
types 239 stats, IPv6 parameter 67
stealth, IP, enabling at build time 80

626
Index

stf interface refused connections, black hole 76


defined 572 show routines, configuration component 91
STOR command 176 stream sockets
Stream Control Transmission Protocol, see using 266
SCTP 93 zero-copy 275
stream sockets TCP debugging configuration component 77
client-server communication 266 TCP v4, configuration component 73
code example 266 TCP v6 configuration component 86
using 266 tcp, TCP run-time configuration parameters 61
strict_init, SCTP configuration parameter 56 TCP/IP
strict_sacks, SCTP configuration parameter 56 defined 572
SUBNET_VLAN, compiler option 538 TCP_ALWAYS_KEEPALIVE_CFG 75
subnets_are_local, IP parameter 54 TCP_BLACKHOLE_CFG 76
setting at build time 80 TCP_DELACK_ENABLED_CFG 76
SUBNETS_ARE_LOCAL_CFG 80 TCP_DELACKTIME_CFG 75
SYN_SEN connections, aborting 84 TCP_DO_NEWRENO_CFG 77
syncache, TCP run-time configuration TCP_DO_RFC1323_CFG 73
parameters 62 TCP_DO_RFC1644_CFG 74
syncookies, TCP configuration parameter 61 TCP_DROP_SYNFIN_CFG 76
sysBootParams.bad 344 TCP_INFLIGHT_DEBUG 74
sysBootParams.ead 344 TCP_INFLIGHT_ENABLE 74
system pool TCP_INFLIGHT_MAX 74
configuring 28 TCP_INFLIGHT_MIN 74
management structures of TCP_KEEPCNT_CFG 75
location in memory 36 TCP_KEEPIDLE_CFG 74
memory allocation for 36 TCP_KEEPINIT_CFG 74
number of clBlk structures in 36 TCP_KEEPINTVL_CFG 75
number of mBlk structures in 35 TCP_LOCAL_SLOWSTART_FLIGHTSIZE_CFG 7
per-size count of buffers in 37 6
storage buffers TCP_LOG_IN_VAIN_CFG 75
allocating memory for 37 TCP_MSL_CFG 75
location in memory 37 TCP_MSSDFLT_CFG 73
supported buffer sizes 36 TCP_PATH_MTU_DISCOVERY_CFG 76
TCP_REASS_ENDPT_MAX_CFG 76
TCP_REASS_GLOBAL_MAX_CFG 76
TCP_RECVSPACE_CFG 75
T TCP_SENDSPACE_CFG 75
TCP_SLOWSTART_FLIGHTSIZE_CFG 76
tasks, priority inversion of 22
TCP_SND_SIZE_DFLT
taskSpawn( ) 119
zbuf sockets and 276
tbrsize, ALTQ and 405
TCP_V6MSSDFLT_CFG 86
tcbhashsize, TCP configuration parameter 61
tcpLib 19, 73
TCP (Transmission Control Protocol) Index
tcpShow, associated configuration component 91
connections, incoming, logging 75
telnet
Maximum Segment Size 73
server, configuring 169
packets, dropping, SYN+FIN set 76

627
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

Telnet client TOS_SET( ) 319


component 171 transport layer
in an RTP 215 defined 572
TELNETD_MAX_CLIENTS 169 troubleshooting
TELNETD_PARSER_HOOK 170 IPv6 connectivity 25
TELNETD_PORT 169 network connections 23
TELNETD_TASKFLAG 169 TTCP, RFC 1644 extensions 61
telnetdLib, Telnet server, configuration component ttl, IP parameter 54
for 169 setting at build time 79
templateEnd.c (END drivers) 473 tunneling 444
terms, glossary of 567 defined 572
TFTP (Trivial File Transfer Protocol) ICMP error messages 84
client 161 IPv6 packets using a gif 449
security (-s option) 162 IPv6 packets using an stf 447
server 162 txSem field (memory leaks) 509
remote, configuration of 162
VxWorks, configuration of 162
TFTP client
in an RTP 215 U
TFTP server
UDP (User Datagram Protocol)
in an RTP 215
checksum 77
TFTP_SERVER_DIRECTORYNAMES 163
datagram size, maximum
TFTP_SERVER_MAXCONNECTIONS 163
incoming 78
TFTP_SERVER_NOCONTROL 163
outgoing 78
TFTP_SERVER_STACKSIZE 162
datagram sockets
tftpboot on UNIX host 162
using 255
tftpCopy( ) 161
defined 572
tftpd 162
packets, logging 77
tftpdLib, configuration component for 162
show routines, configuration component 91
tftpdTask, configuration parameters for 162
UDP v6 configuration component 86
tftpLib, configuration component for 161
udp, UDP run-time configuration parameters 62
tftpXfer( ) 161
UDP_BLACKHOLE_CFG 78
time to live (TTL) on IP packets, maximum 79
UDP_LOG_IN_VAIN_CFG 77
TIME_WAIT 252
UDP_MAXDGRAM_CFG 78
tNetTask 21
UDP_RECVSPACE_CFG 78
configuration component 18
UDP_SND_SIZE_DFLT
priority of 22
zbuf sockets and 276
stack size for 23
UDPCKSUM_CFG 77
task options for 23
udpLib 20, 77
token bucket regulator, ALTQ and 404
udpShow, configuration component 91
TOS value
Use machine clock parameter 410
adding to a routing socket message 319
use_deprecated, IPv6 parameter 67
extracting from a routing socket message 311,
setting at build time 88
313
use_tempaddr, IPv6 parameter 68
TOS_GET( ) 313

628
Index

useloopback, link layer Ethernet parameter 69 virtual stack instance 117


setting at build time 81 selecting 119
user name for FTP6 160 shell commands, and 119
usrGetSockOpt( ) 532 showing status information for 119
usrNetDhcprCfg.c 192 task functions, and 119
usrNetDhcpsCfg.c 196 virtual stack number 117
usrNetInit( ) 178 VIRTUAL_STACK 113
usrSetSockOpt( ) 533 vlanTagLib, deprecated library 538
usrSockAccept( ) 525 vlanTagLib, deprecated library, using 560
usrSockBind( ) 526 VPRN (Virtual Private Routed Network) 112
usrSockClose ) 534 VS_APPLTIMEO_CFG 113
usrSockClose( ) 533 VS_DELTIMEO_CFG 113
usrSockConnect( ) 526 VS_SOCKTIMEO_CFG 113
usrSockConnectWithTimeout( ) 527 vsexec( ) 119
usrSocket( ) 531 VSID (Virtual Stack ID) 117
usrSockGetpeername( ) 527 vsLib 117
usrSockGetsockname( ) 527 vsNumSet( ) 119
usrSockIoctl( ) 535 vsShow 114
usrSockLibInit( ) 525 vsShow( ) 119
usrSockListen( ) 528
usrSockRead( ) 534
usrSockReadRtn( ) 533
usrSockRecv( ) 528 W
usrSockRecvFrom( ) 529, 534
WAIT_FOREVER and rcmd( ) 164
usrSockRecvMsg( ) 529
walk timer value, router renumbering, IPv6 88
usrSockSend( ) 530
well-known port numbers 245
usrSockSendMsg( ) 530
Wind River Firewall
usrSockSendto( ) 530
required by ALTQ 400
usrSockShutDown( ) 531
Wind River Platforms, features unique to
usrSockSockIoctlRtn( ) 533
802.1Q VlAN tagging 537
usrSockSockWriteRtn( ) 533
ALTQ 400
usrSockSockZbufRtn( ) 533
IGMPv2 router 378
usrSockWrite( ) 534
IGMPv3 host 378
list of 1
MLD 394
V MLDv2 394
SCTP 93
v6mssdflt, TCP configuration parameter 61 virtual TCP/IP stacks 111
v6only, IPv6 configuration parameter 68 Workbench, building ALTQ 406
v6only, IPv6 parameter write( ), sockets 249
setting at build time 88 wrong interface, ARP packets logging 82
valid_cookie_life, SCTP configuration WRS ALTQ, component 407 Index
parameter 57
virtual stack configuration component 113

629
Wind River Network Stack for VxWorks 6
Programmer’s Guide, 3.1

X using 273
zero-copy TCP 275
XDR (External Data Representation) ZBUF_BEGIN 279
basic networking support 20 ZBUF_END 279
RPC and 166 ZBUF_SEG 278
zbufCreate( ) 279
zbufCut( ) 281
freeing data buffers 281
Z zbufDelete( ) 279
zbufDup( ) 280
zbuf sockets zbufExtractCopy( ) 280
see online zbufLib; zbufSockLib zbufInsert( ) 280
advantages 287 zbufInsertBuf( ) 279
buffer size issues 276 zbufInsertCopy( ) 280
code examples zbufLength( ) 280
display routine 285 zbufLib 276
TCP server, converting a 287 zbufSegData( ) 282
configuration component for 276 zbufSegFind( ) 281
data structures 277 zbufSegLength( ) 281
byte locations 278 zbufSegNext( ) 281
creating 279 zbufSegPrev( ) 281
deleting 279 zbufSockBufSend( ) 277
dividing in two 281 zbufSockBufSendto( ) 277
example 282 zbufSockLib 276
handling 279 zbufSockLibInit( ) 286
illustrated 278 zbufSockRecv( ) 286
length, determining 280 zbufSockRecvfrom( ) 286
offsets 278 zbufSockSend( ) 286
segment IDs 278 zbufSockSendto( ) 286
segments 281 zbufSplit( ) 281
data, inserting 280 zero-copy TCP 275
example 282
including support for 276
interoperability 276
limitations 286
removing data 281
segments
byte locations, determining 281
data location, determining 282
length, determining 281
reading 281
sharing 280
sending existing buffers 277
shared buffers, managing 277
socket calls 286

630

You might also like