Intel IXA SDK ACE Programming Framework - Department of ...
Intel IXA SDK ACE Programming Framework - Department of ...
Intel IXA SDK ACE Programming Framework - Department of ...
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Intel</strong> ® <strong>IXA</strong> <strong>SDK</strong> <strong>ACE</strong> <strong>Programming</strong><br />
<strong>Framework</strong><br />
<strong>IXA</strong> <strong>SDK</strong> 2.0 Developer’s Guide<br />
August 2001<br />
Document Number: A71582-001
Revision History<br />
Revision Date Revision Description<br />
August 2001 3.3 <strong>SDK</strong> 2.0 release.<br />
Information in this document is provided in connection with <strong>Intel</strong> ® products. No license, express or implied, by estoppel or otherwise, to any intellectual<br />
property rights is granted by this document. Except as provided in <strong>Intel</strong>’s Terms and Conditions <strong>of</strong> Sale for such products, <strong>Intel</strong> assumes no liability<br />
whatsoever, and <strong>Intel</strong> disclaims any express or implied warranty, relating to sale and/or use <strong>of</strong> <strong>Intel</strong> products including liability or warranties relating to<br />
fitness for a particular purpose, merchantability, or infringement <strong>of</strong> any patent, copyright or other intellectual property right. <strong>Intel</strong> products are not<br />
intended for use in medical, life saving, or life sustaining applications.<br />
<strong>Intel</strong> may make changes to specifications and product descriptions at any time, without notice.<br />
Designers must not rely on the absence or characteristics <strong>of</strong> any features or instructions marked “reserved” or “undefined.” <strong>Intel</strong> reserves these for<br />
future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them.<br />
The product may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current<br />
characterized errata are available on request.<br />
<strong>Intel</strong> Corporation might have patents or pending patent applications covering subject matter in this document. The furnishing <strong>of</strong> this document does not<br />
give any license to these patents.<br />
This document as well as the s<strong>of</strong>tware and hardware described in it are furnished under license and may only be used or copied in accordance with<br />
the terms <strong>of</strong> the license. The information in this document is furnished for informational use only, is subject to change without notice, and should not be<br />
construed as a commitment by <strong>Intel</strong> Corporation. <strong>Intel</strong> Corporation assumes no responsibility or liability for any errors or inaccuracies that may appear<br />
in this document or any s<strong>of</strong>tware that may be provided in association with this document. Except as permitted by such license, no part <strong>of</strong> this document<br />
may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without the express written consent <strong>of</strong> <strong>Intel</strong> Corporation.<br />
Contact your local <strong>Intel</strong> sales <strong>of</strong>fice or your distributor to obtain the latest specifications and before placing your product order.<br />
Copies <strong>of</strong> documents which have an ordering number and are referenced in this document, or other <strong>Intel</strong> literature may be obtained by calling<br />
1-800-548-4725 or by visiting <strong>Intel</strong>’s website at http://www.intel.com<br />
Copyright © <strong>Intel</strong> Corporation, 2001. All rights reserved.<br />
*Other names and brands may be claimed as the property <strong>of</strong> others.<br />
This product includes s<strong>of</strong>tware developed by parties other than <strong>Intel</strong>. See the back page <strong>of</strong> this document for a list <strong>of</strong> copyrights and license<br />
agreements.
Contents<br />
About This Guide. . . . . . . . . . . . . . . . . . . . . . . . . . ix<br />
Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix<br />
In This Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix<br />
Other Sources <strong>of</strong> Information . . . . . . . . . . . . . . . . . . . . . . . xi<br />
Typographic Conventions . . . . . . . . . . . . . . . . . . . . . . . . xi<br />
Installation Path . . . . . . . . . . . . . . . . . . . . . . . . . . . xii<br />
Syntax Example . . . . . . . . . . . . . . . . . . . . . . . . . . . xii<br />
Contacting <strong>Intel</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii<br />
Web and Internet Sites . . . . . . . . . . . . . . . . . . . . . . . . xii<br />
Customer Support Technicians . . . . . . . . . . . . . . . . . . . . xiii<br />
Chapter 1 Introduction and Overview . . . . . . . . . . . . . . . . . . . . 1<br />
Network Service Applications . . . . . . . . . . . . . . . . . . . . . . . 1<br />
Packet Classification . . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />
The <strong>IXA</strong> Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />
Logical Elements <strong>of</strong> an <strong>IXA</strong> Application . . . . . . . . . . . . . . . . . . . 3<br />
The Data Plane . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />
The Control Plane . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
The Management Plane . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
Dividing Tasks Among Code Modules . . . . . . . . . . . . . . . . . . 5<br />
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling. . . . . . . . . . . . 5<br />
Packet Processing and <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . 5<br />
Writing <strong>ACE</strong>s using C, NCL and <strong>IXA</strong> IDL. . . . . . . . . . . . . . . . . 6<br />
Predefined <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
Accelerated <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
Dividing Tasks Among <strong>ACE</strong> Types . . . . . . . . . . . . . . . . . . . 8<br />
Using Stack <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
OMS for Global Application Services . . . . . . . . . . . . . . . . . . . 10<br />
Creating <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
Defining the Traffic Flow Path with Targets . . . . . . . . . . . . . . . 11<br />
Contents<br />
iii<br />
Revision 3.3, August 2001
Communication Among <strong>ACE</strong>s. . . . . . . . . . . . . . . . . . . . . 12<br />
Micro<strong>ACE</strong> Resource Manager . . . . . . . . . . . . . . . . . . . . . 13<br />
Hardware Architecture: The IXP1200 Network Processor . . . . . . . . . . 14<br />
S<strong>of</strong>tware Configuration . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
Hardware Configuration . . . . . . . . . . . . . . . . . . . . . . . 15<br />
Deploying Applications. . . . . . . . . . . . . . . . . . . . . . . . 17<br />
Components <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> for the IXP1200 . . . . . . . . . . . . . . . . 17<br />
Chapter 2 Elements <strong>of</strong> an Application . . . . . . . . . . . . . . . . . . . . 19<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
The Object Management System . . . . . . . . . . . . . . . . . . . . . 20<br />
Parts <strong>of</strong> the OMS. . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />
Accessing the OMS. . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
Naming Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
For More Information . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
<strong>ACE</strong>s and Support Structures. . . . . . . . . . . . . . . . . . . . . . . 22<br />
Creating <strong>ACE</strong>s. . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />
Support Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
Additional Services . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
Supporting Languages . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />
Micro<strong>ACE</strong> Support Services . . . . . . . . . . . . . . . . . . . . . . . 24<br />
The Application Building Process . . . . . . . . . . . . . . . . . . . . . 25<br />
Chapter 3 Compiling and Testing Applications . . . . . . . . . . . . . . . 29<br />
Overview <strong>of</strong> the <strong>ACE</strong> Compilation and Linking Process . . . . . . . . . . . 29<br />
Intermediate Compilation . . . . . . . . . . . . . . . . . . . . . . . 29<br />
Compiling and Linking Source Files . . . . . . . . . . . . . . . . . . 30<br />
Compiling Kernel <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . 31<br />
Compiling Micro<strong>ACE</strong>s. . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />
Using Makefiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33<br />
Debugging an Application . . . . . . . . . . . . . . . . . . . . . . . . 33<br />
Chapter 4 Configuring and Starting <strong>IXA</strong> Systems . . . . . . . . . . . . . . 35<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
For Additional Information . . . . . . . . . . . . . . . . . . . . . . 36<br />
Using Startup Scripts and Configuration Files . . . . . . . . . . . . . . . 36<br />
Starting and Initializing Interface <strong>ACE</strong>s . . . . . . . . . . . . . . . . . 37<br />
Microengine Threads . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
The System Configuration File . . . . . . . . . . . . . . . . . . . . . . 37<br />
Configuring Network Interfaces . . . . . . . . . . . . . . . . . . . . 38<br />
Identifying Microcode Images . . . . . . . . . . . . . . . . . . . . . 38<br />
Starting and Configuring Aces . . . . . . . . . . . . . . . . . . . . . 38<br />
Setting Up Particular Configurations . . . . . . . . . . . . . . . . . . . 39<br />
Configuring an L2 Bridge . . . . . . . . . . . . . . . . . . . . . . . 40<br />
System Configuration File . . . . . . . . . . . . . . . . . . . . . 40<br />
iv<br />
Contents<br />
Revision 3.3, August 2001
L2 Bridging Configuration File . . . . . . . . . . . . . . . . . . . 41<br />
Configuring an L3 Forwarder . . . . . . . . . . . . . . . . . . . . . 42<br />
System Configuration File . . . . . . . . . . . . . . . . . . . . . 42<br />
L3 Forwarder Configuration File . . . . . . . . . . . . . . . . . . 43<br />
Configuring an L3 Forwarder with NAT . . . . . . . . . . . . . . . . 44<br />
System Configuration File . . . . . . . . . . . . . . . . . . . . . 44<br />
NAT Configuration File . . . . . . . . . . . . . . . . . . . . . . 45<br />
Launching Application <strong>ACE</strong>s. . . . . . . . . . . . . . . . . . . . . . . 46<br />
Chapter 5 Controlling Packet Flow . . . . . . . . . . . . . . . . . . . . . . 47<br />
Defining Packet Flow . . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />
Physical Packet Flow . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />
Logical Packet Flow . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />
Binding Targets as Packet Destinations . . . . . . . . . . . . . . . . . . 48<br />
Binding Targets and <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . 49<br />
Unbound Targets . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />
Defining Additional Targets . . . . . . . . . . . . . . . . . . . . . . . 50<br />
Directing Packets to a Target . . . . . . . . . . . . . . . . . . . . . . . 51<br />
Using Targets for Packet Processing . . . . . . . . . . . . . . . . . . . . 51<br />
Serial Packet Flow . . . . . . . . . . . . . . . . . . . . . . . . . . 51<br />
Packet Flow Redirection . . . . . . . . . . . . . . . . . . . . . . . 52<br />
Receiving and Transmitting on Network Interface Ports . . . . . . . . . . . 53<br />
See Also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54<br />
Chapter 6 Writing Micro<strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />
Micro<strong>ACE</strong> Architectural Elements . . . . . . . . . . . . . . . . . . . . 56<br />
Architecture Summary . . . . . . . . . . . . . . . . . . . . . . . . 57<br />
Loading Micro<strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . 58<br />
Setting Up a Processing Pipeline for Micro<strong>ACE</strong>s . . . . . . . . . . . . . 59<br />
Creating Static Bindings . . . . . . . . . . . . . . . . . . . . . . 60<br />
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong> . . . . . . . . . . . . . . . . 61<br />
Exception Packet Handling . . . . . . . . . . . . . . . . . . . . . . 62<br />
Initializing a Micro<strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . . 62<br />
Initialization Example . . . . . . . . . . . . . . . . . . . . . . . 63<br />
Terminating a Micro<strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . . 64<br />
Termination Example . . . . . . . . . . . . . . . . . . . . . . . 64<br />
Writing an Exception Packet Handler. . . . . . . . . . . . . . . . . . 64<br />
Exception Packet Handler Example . . . . . . . . . . . . . . . . . 65<br />
Allocating Memory for Shared Data . . . . . . . . . . . . . . . . . . 65<br />
Shared Memory Table Example . . . . . . . . . . . . . . . . . . . . 66<br />
Microcode Side: Hash Initialization and Table Implementation . . . . . 66<br />
Core Processor Side: Core Component Hashing. . . . . . . . . . . . 67<br />
Configuring Micro<strong>ACE</strong>s with Crosscalls . . . . . . . . . . . . . . . . . . 68<br />
Microblock Types and Groups . . . . . . . . . . . . . . . . . . . . . . 68<br />
Microblock Types . . . . . . . . . . . . . . . . . . . . . . . . . . 69<br />
Contents<br />
v<br />
Revision 3.3, August 2001
Source Microblocks . . . . . . . . . . . . . . . . . . . . . . . . 69<br />
Transform Microblocks . . . . . . . . . . . . . . . . . . . . . . 70<br />
Sink Microblocks . . . . . . . . . . . . . . . . . . . . . . . . . 70<br />
Examples <strong>of</strong> Microblocks . . . . . . . . . . . . . . . . . . . . . . . 70<br />
Writing a Dispatch Loop . . . . . . . . . . . . . . . . . . . . . . . . . 71<br />
Dispatch Loop Global Registers . . . . . . . . . . . . . . . . . . . . 72<br />
Defining Additional Global Registers . . . . . . . . . . . . . . . . 73<br />
Implementing Control Flow . . . . . . . . . . . . . . . . . . . . . . 73<br />
Dispatch Loop Example. . . . . . . . . . . . . . . . . . . . . . . . 73<br />
Writing a Microblock . . . . . . . . . . . . . . . . . . . . . . . . . . 75<br />
Returning Values to the Dispatch Loop . . . . . . . . . . . . . . . . . 75<br />
Transmitting a Packet . . . . . . . . . . . . . . . . . . . . . . . . 75<br />
Sending an Exception. . . . . . . . . . . . . . . . . . . . . . . . . 76<br />
Micro<strong>ACE</strong> Design Example . . . . . . . . . . . . . . . . . . . . . . . 77<br />
Chapter 7 Interface <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . 79<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79<br />
Interface <strong>ACE</strong> Crosscalls . . . . . . . . . . . . . . . . . . . . . . . 80<br />
Source Code Location . . . . . . . . . . . . . . . . . . . . . . . . 81<br />
Initializing Interface <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . 81<br />
Creating a Microcode Image with an Interface <strong>ACE</strong> Microblock . . . . . . 81<br />
Starting, Naming, and Binding Interface <strong>ACE</strong>s . . . . . . . . . . . . . . 82<br />
The Input <strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83<br />
Configuring Interface <strong>ACE</strong>s Using Crosscalls . . . . . . . . . . . . . . 83<br />
Responding to Input <strong>ACE</strong> Configuration Crosscalls . . . . . . . . . . . 84<br />
Managing Physical Ports . . . . . . . . . . . . . . . . . . . . . . . 84<br />
Managing Logical Port Configuration. . . . . . . . . . . . . . . . . . 85<br />
The Output <strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85<br />
Sample Output Configurations . . . . . . . . . . . . . . . . . . . . 86<br />
Chapter 8 Stack and Library <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . 87<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87<br />
The Stack <strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88<br />
Starting and Configuring the Stack <strong>ACE</strong> . . . . . . . . . . . . . . . . 88<br />
The L3 Forwarder Library <strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . 89<br />
Starting the Forwarder <strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . 90<br />
Binding the Targets . . . . . . . . . . . . . . . . . . . . . . . . . 90<br />
Configuring the Forwarder . . . . . . . . . . . . . . . . . . . . . . 90<br />
The L2 Bridging Library <strong>ACE</strong>. . . . . . . . . . . . . . . . . . . . . . . 91<br />
Packet Processing . . . . . . . . . . . . . . . . . . . . . . . . . . 92<br />
Starting the L2 Bridger . . . . . . . . . . . . . . . . . . . . . . . . 93<br />
Configuring the L2 Bridger . . . . . . . . . . . . . . . . . . . . . . 94<br />
The NAT Library <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />
Packet Processing . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />
Special Handling. . . . . . . . . . . . . . . . . . . . . . . . . . . 95<br />
FTP Packet Handling . . . . . . . . . . . . . . . . . . . . . . . 95<br />
TCP Fragment Handling . . . . . . . . . . . . . . . . . . . . . . 96<br />
vi<br />
Contents<br />
Revision 3.3, August 2001
ICMP Error Packet Handling . . . . . . . . . . . . . . . . . . . . 96<br />
Starting the NAT <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . . . . 96<br />
Binding the Targets . . . . . . . . . . . . . . . . . . . . . . . . . 97<br />
Configuring the NAT library <strong>ACE</strong>s. . . . . . . . . . . . . . . . . . . 98<br />
Chapter 9 Classifying Packets Using NCL . . . . . . . . . . . . . . . . . . 99<br />
How <strong>ACE</strong>s Handle Packets . . . . . . . . . . . . . . . . . . . . . . . 99<br />
What’s in the NCL Rules File . . . . . . . . . . . . . . . . . . . . . . 100<br />
Classification Elements . . . . . . . . . . . . . . . . . . . . . . . . 100<br />
Sets and Searches . . . . . . . . . . . . . . . . . . . . . . . . . . 100<br />
Defining Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101<br />
Defining Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . 102<br />
How Rules Are Evaluated . . . . . . . . . . . . . . . . . . . . . . . . 103<br />
What Rules Do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104<br />
Chapter 10 Initializing and Acting on Packets in an <strong>ACE</strong> . . . . . . . . . 105<br />
<strong>ACE</strong> Code Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 105<br />
Initializing the <strong>ACE</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . 106<br />
Defining ASL Objects. . . . . . . . . . . . . . . . . . . . . . . . . 106<br />
Defining the Initialization Function . . . . . . . . . . . . . . . . . . 107<br />
Defining Action and Utility Functions . . . . . . . . . . . . . . . . . . . 108<br />
Defining Action Functions . . . . . . . . . . . . . . . . . . . . . . 108<br />
Action Function Return Values . . . . . . . . . . . . . . . . . . . 108<br />
Predefined Default Action Function . . . . . . . . . . . . . . . . . 109<br />
For More Information . . . . . . . . . . . . . . . . . . . . . . . 109<br />
Defining Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . 109<br />
Defining Utility Functions . . . . . . . . . . . . . . . . . . . . . . 109<br />
What Action Functions Do . . . . . . . . . . . . . . . . . . . . . . . . 110<br />
Chapter 11 Communication Within an Application . . . . . . . . . . . . . 113<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113<br />
Defining Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . 114<br />
Making and Receiving Remote Calls . . . . . . . . . . . . . . . . . . 114<br />
When to Use Crosscalls . . . . . . . . . . . . . . . . . . . . . . . . 115<br />
Defining Crosscall Interfaces . . . . . . . . . . . . . . . . . . . . . . . 116<br />
Generated Files . . . . . . . . . . . . . . . . . . . . . . . . . . . 116<br />
Organizing Call Operations . . . . . . . . . . . . . . . . . . . . . . 117<br />
Defining Call Operations . . . . . . . . . . . . . . . . . . . . . . . . 118<br />
Operation Names . . . . . . . . . . . . . . . . . . . . . . . . . . 119<br />
Invocation Types for Operations . . . . . . . . . . . . . . . . . . . . . 120<br />
One-way Operations . . . . . . . . . . . . . . . . . . . . . . . . . 120<br />
Two-way Operations . . . . . . . . . . . . . . . . . . . . . . . . . 120<br />
Deferred Operations . . . . . . . . . . . . . . . . . . . . . . . . . 121<br />
Handling Asynchronous Responses with a Callback Function . . . . . 121<br />
Specifying Timeouts . . . . . . . . . . . . . . . . . . . . . . . . . 122<br />
Declaring Argument Directions . . . . . . . . . . . . . . . . . . . . 122<br />
Contents<br />
vii<br />
Revision 3.3, August 2001
Integrating Crosscalls with Applications . . . . . . . . . . . . . . . . . . 123<br />
Threads and Crosscalls . . . . . . . . . . . . . . . . . . . . . . . . 124<br />
Crosscalls and Library <strong>ACE</strong>s . . . . . . . . . . . . . . . . . . . . . 124<br />
Initializing and Terminating Interfaces. . . . . . . . . . . . . . . . . . . 125<br />
Initializing the Client . . . . . . . . . . . . . . . . . . . . . . . . . 125<br />
Client Initialization Example . . . . . . . . . . . . . . . . . . . . . 125<br />
Initializing the Server. . . . . . . . . . . . . . . . . . . . . . . . . 128<br />
Server Initialization Example . . . . . . . . . . . . . . . . . . . . . 129<br />
Initializing Function Pointers . . . . . . . . . . . . . . . . . . . . . 130<br />
Invoking Crosscall Functions . . . . . . . . . . . . . . . . . . . . . . . 130<br />
Opening a Crosscall Connection . . . . . . . . . . . . . . . . . . . . 131<br />
Remote Call Example. . . . . . . . . . . . . . . . . . . . . . . . . 131<br />
Passing Crosscall Arguments . . . . . . . . . . . . . . . . . . . . . . . 133<br />
Client Side Parameter Passing . . . . . . . . . . . . . . . . . . . . . 134<br />
What the Stub Function Does to Passed Parameters . . . . . . . . . . 135<br />
Server Side Parameter Passing . . . . . . . . . . . . . . . . . . . . . 135<br />
Passing Values in a One-way Call . . . . . . . . . . . . . . . . . . . 136<br />
Passing Values in a Two-way Call . . . . . . . . . . . . . . . . . . . 136<br />
Passing Values in a Deferred Call . . . . . . . . . . . . . . . . . . . 137<br />
Chapter 12 Crosscall Example . . . . . . . . . . . . . . . . . . . . . . . . 139<br />
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139<br />
Example Interface Definition . . . . . . . . . . . . . . . . . . . . . . . 140<br />
Generated Stub Files . . . . . . . . . . . . . . . . . . . . . . . . . 140<br />
Generated Skeleton Files . . . . . . . . . . . . . . . . . . . . . . . 143<br />
Writing the Crosscall Client . . . . . . . . . . . . . . . . . . . . . . . 144<br />
Writing the Crosscall Server . . . . . . . . . . . . . . . . . . . . . . . 152<br />
Terminating the Server . . . . . . . . . . . . . . . . . . . . . . . . 159<br />
Chapter 13 Using Sets <strong>of</strong> Data to Classify Packets . . . . . . . . . . . . . 161<br />
Overview <strong>of</strong> Sets and Searches . . . . . . . . . . . . . . . . . . . . . . 161<br />
When to Use Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162<br />
Defining Sets and Searches . . . . . . . . . . . . . . . . . . . . . . . 162<br />
Defining Sets in NCL . . . . . . . . . . . . . . . . . . . . . . . . . 162<br />
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163<br />
For More Information . . . . . . . . . . . . . . . . . . . . . . . 164<br />
Defining Sets in ASL . . . . . . . . . . . . . . . . . . . . . . . . . 164<br />
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164<br />
Initializing and Populating Sets . . . . . . . . . . . . . . . . . . . . . . 165<br />
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165<br />
For More Information . . . . . . . . . . . . . . . . . . . . . . . 167<br />
How to Use Sets and Searches . . . . . . . . . . . . . . . . . . . . . . 167<br />
Using Searches in Rules. . . . . . . . . . . . . . . . . . . . . . . . 167<br />
Using Actions to Modify Sets . . . . . . . . . . . . . . . . . . . . . 167<br />
Deleting Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168<br />
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169<br />
viii<br />
Contents<br />
Revision 3.3, August 2001
About This Guide<br />
This guide introduces you to the <strong>Intel</strong> ® Internet Exchange Architecture (<strong>IXA</strong>) s<strong>of</strong>tware<br />
development kit (<strong>SDK</strong>). This s<strong>of</strong>tware enables you to develop and deliver<br />
networking applications that define rules to classify network packet traffic, and take<br />
actions based on these rules to manage the network traffic.<br />
To develop these networking applications, you need the following:<br />
l The <strong>IXA</strong> <strong>SDK</strong>, a full set <strong>of</strong> tools for developing applications and run-time libraries<br />
for delivering applications<br />
l<br />
A board or system containing the <strong>Intel</strong> IXP1200 network processor, a high-speed<br />
packet-processing chip, such as the IXDP1200 Advanced Development Platform.<br />
This guide helps you get started creating and testing networking applications for<br />
IXP1200s using the <strong>IXA</strong> <strong>SDK</strong>.<br />
Audience<br />
This guide is intended for s<strong>of</strong>tware developers who will design, develop, and deliver<br />
network applications that must process packets at high speed. It assumes that you are<br />
familiar with the following:<br />
l<br />
l<br />
l<br />
C programming<br />
The Linux * and GNU development environment and toolset<br />
Realtime network applications<br />
In This Guide<br />
This guide includes the following chapters:<br />
l<br />
Chapter 1, “Introduction and Overview,” which gives an overview <strong>of</strong> the <strong>IXA</strong><br />
application architecture and system s<strong>of</strong>tware<br />
About This Guide<br />
ix<br />
Revision 3.3, August 2001
In This Guide<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Chapter 2, “Elements <strong>of</strong> an Application,” which introduces the <strong>IXA</strong> system s<strong>of</strong>tware,<br />
the C structures that support the <strong>ACE</strong> model, the error handling system,<br />
and the application building process<br />
Chapter 3, “Compiling and Testing Applications,” which explains the compilation<br />
model for an application containing <strong>ACE</strong>s<br />
Chapter 4, “Configuring and Starting <strong>IXA</strong> Systems,” which explains how to<br />
configure the ports and start the <strong>ACE</strong>s for an <strong>IXA</strong> system<br />
Chapter 5, “Controlling Packet Flow,” which introduces targets as destinations<br />
for packets and explains how packets flow into and out <strong>of</strong> an IXP1200 and <strong>ACE</strong>s<br />
within an application<br />
Chapter 6, “Writing Micro<strong>ACE</strong>s,” which explains the architecture <strong>of</strong> micro<strong>ACE</strong>s<br />
and describes how to write them<br />
Chapter 7, “Interface <strong>ACE</strong>s,” which introduces the system-defined micro<strong>ACE</strong>s<br />
that receive and transmit packets on network interface ports<br />
Chapter 8, “Stack and Library <strong>ACE</strong>s,” which introduces the system-defined<br />
micro<strong>ACE</strong> that represents the Linux TCP/IP stack and library <strong>ACE</strong>s that perform<br />
common networking tasks<br />
Chapter 9, “Classifying Packets Using NCL,” which introduces the Network<br />
Classification Language and explains how to use it to evaluate packets and write<br />
classification rules<br />
Chapter 10, “Initializing and Acting on Packets in an <strong>ACE</strong>,” which describes<br />
some <strong>of</strong> the actions that you can take on packets and explains how to implement<br />
action functions<br />
Chapter 11, “Communication Within an Application,” which shows how to use<br />
the crosscall mechanism for remote function calls between <strong>ACE</strong>s and other<br />
programs<br />
Chapter 12, “Crosscall Example,” which demonstrates the use <strong>of</strong> crosscalls<br />
Chapter 13, “Using Sets <strong>of</strong> Data to Classify Packets,” which describes how to<br />
create sets to associate application data with packets, and how to perform and act<br />
on the results <strong>of</strong> searches in the sets<br />
x<br />
About This Guide<br />
Revision 3.3, August 2001
Other Sources <strong>of</strong> Information<br />
Other Sources <strong>of</strong> Information<br />
This guide is part <strong>of</strong> the <strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> documentation set, which also includes:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
<strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> Reference (<strong>IXA</strong> <strong>SDK</strong> Reference), which<br />
describes the <strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> (s<strong>of</strong>tware development kit), including the <strong>IXA</strong> API,<br />
which consists <strong>of</strong> the OMS services library, the action services library (ASL), and<br />
the micro<strong>ACE</strong> Resource Manager; the Network Classification Language (NCL);<br />
the <strong>IXA</strong> IDL interface definition language; and development tools<br />
<strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> Developer’s Guide (<strong>IXA</strong> <strong>SDK</strong> Developer’s<br />
Guide), which provides programmers with conceptual descriptions and<br />
instructions on writing networking applications for the IXP1200 using the <strong>IXA</strong><br />
<strong>SDK</strong><br />
<strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> Tutorial (<strong>IXA</strong> <strong>SDK</strong> Tutorial), which<br />
provides a step-by-step introduction to building a basic <strong>IXA</strong> application<br />
<strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> Release Notes (<strong>IXA</strong> <strong>SDK</strong> Release Notes),<br />
which lists information about the latest s<strong>of</strong>tware release<br />
<strong>Intel</strong> <strong>IXA</strong> <strong>SDK</strong> for the IXP1200 Installation and Setup Guide (<strong>IXA</strong> <strong>SDK</strong> Installation and<br />
Setup Guide), which describes how to install the <strong>IXA</strong> <strong>SDK</strong> and set up the development<br />
environment<br />
Getting Started, which provides a high-level introduction to the product family<br />
and describes supported hardware and s<strong>of</strong>tware configurations<br />
The IXP1200 Microengine Development Environment documentation set, which<br />
includes the following documents:<br />
— IXP1200 Network Processor Family Microcode Programmer’s Reference Manual<br />
— IXP1200 Network Processor Family Microcode Developer Tools User’s Guide<br />
— IXP1200 Network Processor Family Microcode Example S<strong>of</strong>tware<br />
— IXP1200 Network Processor Family Hardware Reference Manual<br />
— IXP1200 Macro Library Reference Manual<br />
— IXP1200 Macro Library Style Guide<br />
— IXDP1200 I/O Option Card Design Guide<br />
— Microengine C Compiler Language Support Reference Manual<br />
— Microengine C Compiler LIBC Reference Manual<br />
In addition, the <strong>Intel</strong> Web site provides valuable information on products, support,<br />
and the company. See “Contacting <strong>Intel</strong>” on page xii.<br />
Typographic Conventions<br />
This document uses the following typographic conventions to help you locate and<br />
identify information:<br />
Italic text<br />
Bold text<br />
Used for new terms, emphasis, and book titles; also identifies arguments<br />
in syntax descriptions.<br />
Identifies keywords and punctuation in syntax descriptions.<br />
About This Guide<br />
xi<br />
Revision 3.3, August 2001
Contacting <strong>Intel</strong><br />
Courier font Identifies file names, folder names, and text that either appears on<br />
the screen or that you are required to type.<br />
NOTE: Provides extra information, tips, and hints regarding the topic.<br />
CAUTION: Identifies important information about actions that could result in<br />
damage to or loss <strong>of</strong> data or could cause the application to behave<br />
in unexpected ways.<br />
WARNING!<br />
Identifies critical information about actions that could result in<br />
equipment failure or bodily injury.<br />
Installation<br />
Path<br />
The pathname <strong>of</strong> the installation directory for the product is indicated by the<br />
following argument:<br />
<strong>SDK</strong>installpath<br />
The environment variable $IXROOT is set to the actual installation path during installation;<br />
you can use this variable if it is set in your environment.<br />
l<br />
l<br />
The default installation path for a Linux development system is /opt/ixasdk.<br />
The default installation path for a Windows NT * development system is<br />
C:\eLinuxIDE-IXP1200\cygwin\opt\ixasdk.<br />
Syntax<br />
Example<br />
Courier font is used for code. In syntax descriptions, bold indicates required<br />
keywords and a punctuation. In examples, bold highlights interesting parts. Italics<br />
indicate values that are to be replaced, such as arguments or file names. The<br />
following figure shows a sample <strong>of</strong> syntax notation.<br />
Keywords, required punctuation<br />
predicate predicate_name { boolean_expression }<br />
Arguments<br />
Contacting <strong>Intel</strong><br />
You can reach <strong>Intel</strong>’s automated support services 24 hours a day, every day at no<br />
charge. The services contain the most up-to-date information about <strong>Intel</strong> products.<br />
You can access installation instructions, troubleshooting information, and general<br />
product information.<br />
Web and<br />
Internet Sites<br />
You can use the Internet to download s<strong>of</strong>tware updates, troubleshooting tips, installation<br />
notes, and more.<br />
l<br />
General online support services are on the World Wide Web at:<br />
xii<br />
About This Guide<br />
Revision 3.3, August 2001
Contacting <strong>Intel</strong><br />
http://support.intel.com<br />
l<br />
Online support services for the IXP1200 network processor are at:<br />
http://support.intel.com/support/network/processor/ixp1200/<br />
For specific types <strong>of</strong> information and services, go to the following Web and Internet<br />
sites:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Corporate: http://www.intel.com<br />
Networking products: http://www.intel.com/network/<br />
<strong>Intel</strong> <strong>IXA</strong> information: http://developer.intel.com/design/ixa/<br />
<strong>IXA</strong> <strong>SDK</strong>: http://www.intel.com/design/network/products/s<strong>of</strong>tware/index.htm<br />
IXP1200 developer site:<br />
http://developer.intel.com/design/network/products/npfamily/ixp1200.htm<br />
FTP host: download.intel.com<br />
FTP directory: /support/network/adapter<br />
Customer<br />
Support<br />
Technicians<br />
l<br />
l<br />
United States and Canada: 1.916.377.7000 (7:00 - 17:00 M-F Pacific Time)<br />
Worldwide access: <strong>Intel</strong> has technical support centers worldwide. Many <strong>of</strong> the<br />
centers are staffed by technicians who speak the local languages. For a list <strong>of</strong> all<br />
<strong>Intel</strong> support centers, their telephone numbers, and the times they are open, go to:<br />
http://support.intel.com/support/9089.htm<br />
About This Guide<br />
xiii<br />
Revision 3.3, August 2001
Contacting <strong>Intel</strong><br />
xiv<br />
About This Guide<br />
Revision 3.3, August 2001
Chapter 1<br />
Introduction and Overview<br />
This chapter introduces you to the tools that <strong>Intel</strong> ® provides to develop and deliver<br />
network service applications using <strong>Intel</strong>’s Internet Exchange Architecture for<br />
theIXP1200 network processor.<br />
This chapter contains the following topics:<br />
l “Network Service Applications” on page 1<br />
l “Logical Elements <strong>of</strong> an <strong>IXA</strong> Application” on page 3<br />
l “The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling” on page 5<br />
l “OMS for Global Application Services” on page 10<br />
l “Hardware Architecture: The IXP1200 Network Processor” on page 14<br />
l “Components <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> for the IXP1200” on page 17<br />
Network Service Applications<br />
Networks have become a core component <strong>of</strong> businesses; their operation is critical to<br />
the businesses’ daily operation. Applications have become increasingly complex in<br />
order to manage, secure, and optimize these networks.<br />
Application developers and equipment manufacturers must develop and enhance<br />
these applications to meet the rapidly changing needs <strong>of</strong> their users while ensuring<br />
that networks operate with optimal performance.<br />
The following are common examples <strong>of</strong> network services applications:<br />
l Firewalls<br />
l Virtual private networks (VPN)<br />
l Intrusion detection systems<br />
l RMON statistical monitoring applications<br />
Revision 3.3, August 2001<br />
Introduction and Overview 1
Network Service Applications<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Load-balancing systems<br />
Quality <strong>of</strong> service (QoS) applications<br />
Voice over IP (VOIP) applications<br />
Protocol conversion<br />
Layer 3 forwarding<br />
Packet<br />
Classification<br />
At the highest level, as shown in the following figure, a network services application<br />
consists <strong>of</strong> the following:<br />
l<br />
l<br />
Interfaces to and from one or more networks (called network interface ports)<br />
Applications that process packets traveling on the networks<br />
Packet flow<br />
Input interface<br />
Application<br />
Output interface<br />
Such an application classifies the packets—that is, it compares the packet contents<br />
against some set <strong>of</strong> selection criteria. It then takes some action determined by the<br />
result <strong>of</strong> the classification and disposes <strong>of</strong> the packets. For example, it might:<br />
l<br />
l<br />
l<br />
View packets and simply decide whether to pass them to another interface or<br />
application, or to drop them<br />
Collect information about the packets and report on the flow <strong>of</strong> data<br />
Manipulate the packets in some way<br />
The following figure shows how packets might flow through a forwarding application.<br />
Packet flow<br />
Input interface<br />
Packet classification and action<br />
Yes<br />
In data table?<br />
No<br />
Good packet?<br />
No<br />
Drop<br />
Output interface<br />
Yes; update data<br />
The <strong>IXA</strong><br />
Solution<br />
The <strong>Intel</strong> Internet Exchange Architecture provides an efficient and flexible hardware<br />
and s<strong>of</strong>tware infrastructure for developing and delivering network services applications.<br />
You can develop applications for this architecture using the application<br />
programming interface (API), the <strong>IXA</strong> API.<br />
2 Introduction and Overview<br />
Revision 3.3, August 2001
Logical Elements <strong>of</strong> an <strong>IXA</strong> Application<br />
Applications that you develop with the <strong>IXA</strong> API are known as <strong>IXA</strong> applications. The<br />
<strong>IXA</strong> s<strong>of</strong>tware development kit (<strong>SDK</strong>) provides tools and libraries that allow you to<br />
quickly and easily develop and deliver <strong>IXA</strong> applications. These applications directly<br />
manipulate packets, independent <strong>of</strong> the protocol layer.<br />
You use the <strong>IXA</strong> <strong>SDK</strong> to produce applications for a hardware configuration that<br />
includes one or more IXP1200 network processors. Both the s<strong>of</strong>tware and hardware<br />
are optimized for maximum efficiency in providing network services.<br />
The rest <strong>of</strong> this document describes:<br />
l<br />
l<br />
l<br />
The logical architecture and major s<strong>of</strong>tware elements <strong>of</strong> an <strong>IXA</strong> application<br />
The IXP1200 network processor, and how you develop and deploy your application<br />
s<strong>of</strong>tware in the hardware environment<br />
The tools and libraries provided by the <strong>IXA</strong> <strong>SDK</strong><br />
Logical Elements <strong>of</strong> an <strong>IXA</strong> Application<br />
To understand the <strong>IXA</strong> s<strong>of</strong>tware architecture, you must understand the basic levels<br />
<strong>of</strong> tasks that a network services application performs. A network services application<br />
typically operates on three logical planes:<br />
l<br />
l<br />
l<br />
The data processing plane<br />
Data plane functions include the handling and forwarding <strong>of</strong> incoming packets at<br />
high speed.<br />
The control plane<br />
Control functions include the handling <strong>of</strong> exceptional cases or errors, and the<br />
creation and maintenance <strong>of</strong> both application objects and the tables or data sets<br />
that the data processing part uses for lookups.<br />
The management plane<br />
The manager for an application creates and initializes the objects in the other<br />
parts, and starts their execution. High-level management can include, for<br />
example, system or object configuration, or stopping and starting application<br />
functions in response to environmental conditions or user input. A manager<br />
might handle alerts, status reports, and other messages that the application generates.<br />
The Data Plane<br />
A part <strong>of</strong> an <strong>IXA</strong> application that performs data plane functions is a data processor<br />
(sometimes called a forwarding element). It receives buffers <strong>of</strong> data (containing cells,<br />
packets, frames, or even generalized I/O buffers) from a network interface, classifies<br />
them according to their protocols or contents, and determines their disposition by<br />
performing lookups in data tables. The data processor handles the fast path—the most<br />
frequent and usual operations—such as packet forwarding. This part <strong>of</strong> an application<br />
is optimized for performance and handles the bulk <strong>of</strong> network traffic.<br />
For the IXP1200, data processors are commonly implemented as micro<strong>ACE</strong>s compiled<br />
specifically for the microengines. (See “Accelerated <strong>ACE</strong>s” on page 7.)<br />
Introduction and Overview 3<br />
Revision 3.3, August 2001
Logical Elements <strong>of</strong> an <strong>IXA</strong> Application<br />
The Control<br />
Plane<br />
A part <strong>of</strong> an <strong>IXA</strong> application that performs control plane functions is a controller<br />
(sometimes called a control element). This part performs complex or time-consuming<br />
tasks that are encountered in the course <strong>of</strong> packet processing.<br />
For example, when a data processor for a routing application encounters a packet for<br />
which there is no entry in the routing table, it can send that packet to the controller.<br />
This leaves the data processor free to continue forwarding traffic while the controller<br />
finds the proper route and adds it to the table, or otherwise handles the exception.<br />
For the IXP1200, controllers are commonly implemented as conventional <strong>ACE</strong>s and<br />
compiled for the core processor, which provides more operating system services.<br />
Another alternative is to implement controllers using third-party protocol stack s<strong>of</strong>tware<br />
modified for use with the <strong>IXA</strong> <strong>SDK</strong>.<br />
The<br />
Management<br />
Plane<br />
A part <strong>of</strong> an <strong>IXA</strong> application that performs management functions is a manager<br />
program. Management tasks can be handled by an <strong>of</strong>f-chip application or by a standard<br />
Linux * application that runs on the IXP1200. The management code for the <strong>IXA</strong><br />
application is commonly part <strong>of</strong> a larger application that includes some sort <strong>of</strong> user<br />
interface. This part can communicate with the control and data processing pieces by<br />
making calls to the IXP1200 system s<strong>of</strong>tware.<br />
The manager program might, for example, get information from a user through a<br />
graphical user interface (GUI) and respond by changing the direction <strong>of</strong> packet flow<br />
between parts <strong>of</strong> the <strong>IXA</strong> application. Similarly, it might respond to an error message<br />
from the controller by displaying a message to a user through a GUI.<br />
In embedded systems, a manager program might implement an application-specific<br />
management protocol between an IXP1200 subsystem and a central management<br />
element; for example, communication between an IXP1200-based line card and a<br />
management card over a chassis backplane.<br />
Data/control flow<br />
Layer 3 Stateful Load<br />
routing firewall balancer<br />
application application application<br />
Management<br />
application<br />
Management<br />
plane<br />
Route<br />
management,<br />
UI<br />
Policy<br />
management,<br />
GUI<br />
Policy<br />
management,<br />
GUI<br />
Control<br />
module<br />
Control<br />
plane<br />
OSPF,<br />
RIP2, ...<br />
Connection<br />
setup<br />
Connection<br />
setup,<br />
resource<br />
allocation<br />
Data<br />
processing<br />
module<br />
Data<br />
plane<br />
Packet<br />
forward<br />
Packet<br />
pass, drop,<br />
NAT, ...<br />
Packet<br />
forward,<br />
NAT<br />
Traffic flow<br />
4 Introduction and Overview<br />
Revision 3.3, August 2001
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling<br />
Dividing Tasks<br />
Among Code<br />
Modules<br />
You can divide the tasks belonging to each functional plane among code modules in<br />
any number <strong>of</strong> ways, depending on the complexity <strong>of</strong> your application. A single<br />
control module, for example, might receive messages from multiple data processing<br />
modules, or you might create separate control modules for different control tasks.<br />
Similarly, you might combine control and management plane tasks into a single code<br />
module, or keep them separate.<br />
Different code modules can be compiled to run on different processors, depending on<br />
what is available and appropriate to a module’s tasks.<br />
l<br />
l<br />
Data processing and control modules are commonly located on an IXP1200<br />
network processor where they can react to and process packets at high speeds.<br />
They can be further optimized by compiling them specifically for different processors<br />
on the IXP1200 network processor.<br />
A manager program might be located on another processor where it has access to<br />
user interfaces, storage, and the full range <strong>of</strong> services provided by the operating<br />
system.<br />
For more information on hardware platforms and deployment options, see “Hardware<br />
Architecture: The IXP1200 Network Processor” on page 14.<br />
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling<br />
In order to encapsulate and modularize the unique tasks involved in packet<br />
processing, the <strong>IXA</strong> API defines a s<strong>of</strong>tware construct called an active computing<br />
element (<strong>ACE</strong>). <strong>ACE</strong>s are represented by a C structure, ix_ace.<br />
Packet<br />
Processing<br />
and <strong>ACE</strong>s<br />
<strong>ACE</strong>s are the primary s<strong>of</strong>tware components for processing packets. Both the data<br />
processing and control parts <strong>of</strong> an application contain <strong>ACE</strong>s. <strong>ACE</strong>s classify the<br />
packets, act on them according to these classifications, and determine their disposition.<br />
You organize <strong>ACE</strong>s as a serial processing pipeline, with packets passed from one<br />
<strong>ACE</strong> to another. Each one can inspect, classify, manipulate, and forward the packets<br />
that it receives.<br />
Packet processing takes place as a sequence <strong>of</strong> steps. Each step is performed by a<br />
separate <strong>ACE</strong>, and consists <strong>of</strong> a classification phase and an action phase.<br />
— During the classification phase, the <strong>ACE</strong> evaluates rules to determine if<br />
specific conditions or criteria exist. If a rule is true, the <strong>ACE</strong> places an associated<br />
action on a queue to be performed after all rules have been evaluated.<br />
More than one rule can be true, in which case all associated actions are queued.<br />
— During the action phase, the <strong>ACE</strong> executes all scheduled actions. If no rules<br />
are true, the <strong>ACE</strong> takes a default action, such as delivering the packet to a<br />
default destination or discarding it. <strong>ACE</strong>s can modify, drop, duplicate, or<br />
simply inspect the packets that they receive. Thus, packets can appear, disappear,<br />
or be changed as they flow through the <strong>ACE</strong>s.<br />
Introduction and Overview 5<br />
Revision 3.3, August 2001
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling<br />
An <strong>ACE</strong> is defined by several distinct source code files. An initialization part, which<br />
creates and initializes needed structures and variables, and the action part, which<br />
defines the associated action functions, are written in C/C++. The classification part <strong>of</strong><br />
the <strong>ACE</strong>, which defines a set <strong>of</strong> packet classification rules, is written in Network Classification<br />
Language (NCL )<br />
Each <strong>ACE</strong> generally performs one type <strong>of</strong> packet handling or data control task. You<br />
can distribute tasks among <strong>ACE</strong>s, and <strong>ACE</strong>s among code modules in any way that is<br />
logical for your application. The following figure shows the high-level architecture <strong>of</strong><br />
a typical <strong>IXA</strong> application.<br />
Managing application<br />
Object creation,<br />
flow control<br />
Error handling, status<br />
<strong>ACE</strong><br />
Control module<br />
<strong>ACE</strong><br />
Data<br />
management<br />
Data initialization,<br />
configuration<br />
Exception cases<br />
Input interface<br />
Output interface<br />
Packet flow<br />
<strong>ACE</strong><br />
<strong>ACE</strong><br />
Data processing modules<br />
You can create your own <strong>ACE</strong>s using the <strong>IXA</strong> API, or you can use predefined <strong>ACE</strong>s<br />
that perform specific network processing tasks, as described below in “Predefined<br />
<strong>ACE</strong>s.”<br />
Your application defines the flow <strong>of</strong> packets among <strong>ACE</strong>s by creating packet destinations<br />
called targets and by binding the targets to other <strong>ACE</strong>s; see “Defining the Traffic<br />
Flow Path with Targets” on page 11.<br />
Writing <strong>ACE</strong>s<br />
using C, NCL<br />
and <strong>IXA</strong> IDL<br />
In the initialization part <strong>of</strong> an <strong>ACE</strong>, you create the <strong>ACE</strong> structure itself, with its<br />
related communication methods and data structures, using the ASL core C library.<br />
In the classification part <strong>of</strong> an <strong>ACE</strong>, rules can compare packet contents against static<br />
values or against dynamic data. You define these rules using the Network Classification<br />
Language (NCL) provided with the <strong>IXA</strong> <strong>SDK</strong>. NCL is a domain-specific objectoriented<br />
language for defining packet classification rules and identifying the associated<br />
actions to be taken when matches occur. This language-based approach makes<br />
it easy for you to specify the required classification criteria.<br />
6 Introduction and Overview<br />
Revision 3.3, August 2001
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling<br />
In the action part <strong>of</strong> an <strong>ACE</strong>, you define the <strong>ACE</strong> infrastructure and action functions<br />
in C/C++. In the action functions, you can use run-time support for networking tasks<br />
provided by the ASL application services. These C/C++ class and function libraries<br />
provide support for handling application-specific operations; for example, TCP/IP<br />
operations such as IP fragmentation and reassembly, Network Address Translation<br />
(NAT), and TCP connection monitoring and stream reconstruction.<br />
For communication between <strong>ACE</strong>s and other parts <strong>of</strong> an application, you define<br />
remote function calls, using an interface definition language, <strong>IXA</strong> IDL. This compiles<br />
to C and becomes part <strong>of</strong> the <strong>ACE</strong>’s C source code. See “Communication Among<br />
<strong>ACE</strong>s” on page 12.<br />
Predefined<br />
<strong>ACE</strong>s<br />
Depending on who develops it and how it is created, an <strong>ACE</strong> can be a user <strong>ACE</strong>, a<br />
library <strong>ACE</strong>, or a system <strong>ACE</strong>. You can combine all three types in an application.<br />
l<br />
l<br />
User <strong>ACE</strong>s<br />
User <strong>ACE</strong>s are those that you develop yourself, defining all <strong>of</strong> the classification<br />
rules and actions.<br />
Library <strong>ACE</strong>s<br />
<strong>Intel</strong> supplies a set <strong>of</strong> predefined library <strong>ACE</strong>s, which provide building blocks for<br />
common application functionality such as layer 2 bridging and layer 3 (IP)<br />
forwarding.<br />
NOTE:<br />
Some library <strong>ACE</strong>s are supplied with source code so that you can configure<br />
them and modify their packet classification criteria and actions. When you<br />
modify a library <strong>ACE</strong>, it becomes a user <strong>ACE</strong> and is no longer supported and<br />
maintained by <strong>Intel</strong>.<br />
l<br />
System <strong>ACE</strong>s<br />
These platform-specific <strong>ACE</strong>s represent hardware network interfaces (interface<br />
<strong>ACE</strong>s) or protocol stacks (stack <strong>ACE</strong>s). The system <strong>ACE</strong>s are not necessarily implemented<br />
like other <strong>ACE</strong>s; they simply mask hardware and system details that are<br />
specific to a particular environment, and look like <strong>ACE</strong>s to your application.<br />
The system <strong>ACE</strong>s act as packet sources and destinations. They are opaque to other<br />
<strong>ACE</strong>s. You can configure system <strong>ACE</strong>s and communicate with them, but you<br />
cannot modify them.<br />
You customize the system initialization scripts to load and start the system <strong>ACE</strong>s<br />
your application and hardware configuration requires. The <strong>IXA</strong> <strong>SDK</strong> supplies<br />
system <strong>ACE</strong>s for the Ethernet * 10/100 and gigabit ports on the IXDP1200<br />
Advanced Development Platform, and for the Linux TCP/IP stack.<br />
Accelerated<br />
<strong>ACE</strong>s<br />
The <strong>ACE</strong> architecture allows an <strong>ACE</strong> to take advantage <strong>of</strong> the speed <strong>of</strong> dedicated<br />
processors. An <strong>ACE</strong> that runs entirely on the core processor is a conventional <strong>ACE</strong>. An<br />
<strong>ACE</strong> that includes code for another processor is called an accelerated <strong>ACE</strong>.<br />
The <strong>IXA</strong> <strong>SDK</strong> provides a type <strong>of</strong> accelerated <strong>ACE</strong> called a micro<strong>ACE</strong>. The micro<strong>ACE</strong><br />
programming model provides a framework for creating a packet-processing application<br />
that makes use <strong>of</strong> the IXP1200’s microengines. A micro<strong>ACE</strong> has two logical<br />
components, running on different processors:<br />
Introduction and Overview 7<br />
Revision 3.3, August 2001
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling<br />
l<br />
l<br />
The core component <strong>of</strong> a micro<strong>ACE</strong> is a complete conventional <strong>ACE</strong>, with<br />
C/C++, NCL, and <strong>IXA</strong> IDL code. The core component runs on the core processor<br />
in the IXP1200.<br />
The acceleration component <strong>of</strong> a micro<strong>ACE</strong>, called a microblock, is hardwarespecific<br />
and is written in IXP1200 microcode (machine code). The microblock runs<br />
on the microengines in the IXP1200. It performs fast-path processing, but can<br />
exchange packets with its core component on the core processor to handle exception<br />
cases.<br />
For more information on hardware platforms and deployment options, see “Hardware<br />
Architecture: The IXP1200 Network Processor” on page 14.<br />
You use micro<strong>ACE</strong>s for optimized, high-speed (fast-path) processing. Because the<br />
IXP1200 network processor contains a number <strong>of</strong> microengines running in parallel,<br />
each with multiple threads, micro<strong>ACE</strong>s provide extremely high efficiency in basic<br />
packet handling. Most system <strong>ACE</strong>s and library <strong>ACE</strong>s are implemented as micro-<br />
<strong>ACE</strong>s.<br />
The <strong>IXA</strong> <strong>SDK</strong> includes a complete set <strong>of</strong> tools, including compilers, linkers, and<br />
debuggers, for working with microcode to develop micro<strong>ACE</strong>s. For more information<br />
on the architecture <strong>of</strong> micro<strong>ACE</strong>s, see Chapter 6, “Writing Micro<strong>ACE</strong>s.”<br />
Dividing Tasks<br />
Among <strong>ACE</strong><br />
Types<br />
Generally, a micro<strong>ACE</strong> looks in a packet to classify it, performs simple transformations<br />
(such as NAT or protocol conversion), and routes it to the appropriate target.<br />
Exceptions are reported to another (conventional) <strong>ACE</strong> for handling. This allows<br />
time-consuming operations to run in parallel without slowing down traffic.<br />
The following figure shows an example <strong>of</strong> a forwarding application that uses a<br />
micro<strong>ACE</strong> for data processing and a conventional <strong>ACE</strong> for control.<br />
8 Introduction and Overview<br />
Revision 3.3, August 2001
The <strong>ACE</strong> <strong>Programming</strong> <strong>Framework</strong> for Packet Handling<br />
Control plane<br />
FwdControl <strong>ACE</strong><br />
Update cache & forward<br />
Full lookup<br />
Forwarding table<br />
Route entry<br />
prefix = 192.0.0.0<br />
ifnum = 82<br />
nexthop = 192.168.0.02<br />
Packet flow<br />
Input interface<br />
Data plane<br />
Forwarding cache<br />
Exception:<br />
Quick lookup<br />
not in cache<br />
Forwarder micro<strong>ACE</strong><br />
Forward<br />
Fast path<br />
Output interface<br />
In this example, the application defines a data table with the forwarding information<br />
on the core processor, and keeps a smaller data cache in the microcode on the microengines.<br />
A micro<strong>ACE</strong> called Forwarder handles most packet forwarding. When it<br />
encounters a packet that does not have an entry in the local forwarding cache, it sends<br />
that packet to a conventional <strong>ACE</strong>, called FwdControl. While the FwdControl <strong>ACE</strong><br />
does a full lookup in the complete forwarding table, the Forwarder <strong>ACE</strong> can<br />
continue to handle traffic flow. When FwdControl is finished, it updates the cache<br />
and, if appropriate, inserts the exception-case packet back into the traffic flow.<br />
l<br />
l<br />
The Resource Manager defines memory management functions for a small<br />
amount <strong>of</strong> memory that can be shared by the microengines and core processor.<br />
For more information, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
The <strong>IXA</strong> API defines data structures and functions for implementing larger data<br />
tables in unshared memory, called sets. For more information, see Chapter 13,<br />
“Using Sets <strong>of</strong> Data to Classify Packets.”<br />
Using Stack<br />
<strong>ACE</strong>s<br />
The <strong>IXA</strong> <strong>SDK</strong> allows you to tie the services <strong>of</strong> the Linux TCP/IP protocol stack into<br />
the structure <strong>of</strong> an <strong>IXA</strong> application.<br />
A system <strong>ACE</strong> called the stack <strong>ACE</strong> enables any other <strong>ACE</strong> in the system to deliver<br />
packets to—or receive packets from—the Linux kernel. You can then use standard<br />
sockets-based application s<strong>of</strong>tware to implement portions <strong>of</strong> an <strong>IXA</strong> application<br />
without having to use the <strong>ACE</strong> s<strong>of</strong>tware model. In this case, other <strong>ACE</strong>s in the system<br />
Introduction and Overview 9<br />
Revision 3.3, August 2001
OMS for Global Application Services<br />
appear, from the Linux TCP/IP stack point <strong>of</strong> view, as standard Ethernet interfaces.<br />
This provides a means for you to re-use existing or third-party protocol stack or<br />
management plane s<strong>of</strong>tware while migrating an application to the <strong>ACE</strong> model.<br />
OMS for Global Application Services<br />
Object Management System (OMS) services are part <strong>of</strong> the <strong>IXA</strong> API. The OMS, part <strong>of</strong><br />
the <strong>IXA</strong> system s<strong>of</strong>tware, is a single logical entity with components distributed<br />
throughout the system. Any <strong>ACE</strong> can make use <strong>of</strong> OMS services. Any program that<br />
must communicate with an <strong>ACE</strong> can do so by registering itself with the OMS as a task.<br />
An application uses global C functions defined by the OMS services to create,<br />
configure, control, and destroy objects and structures in all parts <strong>of</strong> the application,<br />
and to perform global tasks. The primary global services your application requires<br />
are:<br />
l<br />
l<br />
l<br />
Creating and destroying <strong>ACE</strong>s and tasks<br />
Defining and controlling packet flow using targets<br />
Communicating among <strong>ACE</strong>s and tasks<br />
The OMS contains the following parts:<br />
l The Resolver, which creates and deletes <strong>ACE</strong>s, and manages packet flow by<br />
binding <strong>ACE</strong>s and targets.<br />
l<br />
The Name Server, which manages the name space for the OMS, maintaining a<br />
correspondence between names and internal identifiers for <strong>ACE</strong>s, targets and<br />
tasks. The name space allows objects that might be distributed among processors<br />
to address one another unambiguously.<br />
In order to communicate with and through the OMS, a program must create a<br />
communications channel, a separate process or thread containing a communication<br />
access process, or CAP. A program can communicate with both the Resolver and the<br />
Name Server through the same CAP. When you create an <strong>ACE</strong> or task structure, a<br />
CAP is automatically created with it. The OMS provides functions to retrieve the<br />
CAP for use as an argument to other OMS functions.<br />
Creating <strong>ACE</strong>s<br />
An application’s manager program creates and initializes the application’s <strong>ACE</strong>s by<br />
calling Resolver functions in the OMS. To do this, it must first register with the OMS<br />
as a task, using the ASL function ix_task_init. The task provides access to a CAP<br />
channel through which to communicate with the Resolver.<br />
You define an initialization function in the <strong>ACE</strong> executable to create the <strong>ACE</strong> structure<br />
and all support structures such as packet destination targets, data sets and<br />
elements, crosscalls, and events.<br />
When the manager program creates the <strong>ACE</strong>, you pass the <strong>ACE</strong> executable to the<br />
Resolver function ix_res_create_ace. This calls the initialization function and<br />
starts the <strong>ACE</strong>’s main loop, which begins packet and crosscall event processing.<br />
10 Introduction and Overview<br />
Revision 3.3, August 2001
OMS for Global Application Services<br />
The <strong>IXA</strong> <strong>SDK</strong> also supplies utilities to start and stop <strong>ACE</strong>s from the command line or<br />
from a script.<br />
Defining the<br />
Traffic Flow<br />
Path with<br />
Targets<br />
Packets flow from one <strong>ACE</strong> to another, with each <strong>ACE</strong> performing a specific operation.<br />
The packet flow starts with a system <strong>ACE</strong> that represents a network interface<br />
(see “Predefined <strong>ACE</strong>s” on page 7). You determine the order in which packets are<br />
directed from the system <strong>ACE</strong> through intermediate <strong>ACE</strong>s before they are directed<br />
back out to the network through a network interface, or dropped from traffic.<br />
An application defines the paths through which packets flow between <strong>ACE</strong>s by specifying<br />
a set <strong>of</strong> targets. A target is an object within an <strong>ACE</strong> that represents a destination<br />
for packets. Each <strong>ACE</strong> contains a set <strong>of</strong> targets to which it routes packets when it has<br />
finished processing them. Each action ends by directing a packet to a target. For<br />
example, here are three <strong>ACE</strong>s with targets; packet flow among <strong>ACE</strong>s is not yet implemented.<br />
Network interface <strong>ACE</strong><br />
Target T1<br />
Packet flow <strong>ACE</strong> 1<br />
Decision?<br />
Target T2<br />
Target T3<br />
<strong>ACE</strong> 2<br />
Processing<br />
Target T4<br />
The application implements traffic flow between <strong>ACE</strong>s by binding targets in one <strong>ACE</strong><br />
to other <strong>ACE</strong>s. When an application binds a target to an <strong>ACE</strong>, the target serves as the<br />
input queue for that <strong>ACE</strong>. The bound <strong>ACE</strong> is then downstream in the packet flow<br />
from the <strong>ACE</strong> containing the target.<br />
In the following diagram, target T1 is bound to <strong>ACE</strong>1; target T3 is bound to <strong>ACE</strong>2;<br />
and targets T2 and T4 have not yet been bound.<br />
Introduction and Overview 11<br />
Revision 3.3, August 2001
OMS for Global Application Services<br />
Network interface <strong>ACE</strong><br />
Target T1<br />
Packet flow <strong>ACE</strong> 1<br />
Decision?<br />
Target T2<br />
Target T3<br />
<strong>ACE</strong> 2<br />
Processing<br />
Target T4<br />
The management program for an application binds and unbinds targets and <strong>ACE</strong>s<br />
using Resolver functions (ix_res_bind and ix_res_unbind) that are part <strong>of</strong> the<br />
OMS services. The <strong>IXA</strong> <strong>SDK</strong> also supplies utilities to bind <strong>ACE</strong>s and targets from the<br />
command line or from a script.<br />
The target mechanism makes the actual identities <strong>of</strong> the <strong>ACE</strong>s transparent to the<br />
action code that forwards the packets. The management part <strong>of</strong> your application can<br />
change the bindings <strong>of</strong> targets to <strong>ACE</strong>s to alter the path <strong>of</strong> packet flow, without you<br />
having to change the code in the <strong>ACE</strong>s themselves.<br />
For more information, see Chapter 5, “Controlling Packet Flow.”<br />
Communicatio<br />
n Among <strong>ACE</strong>s<br />
<strong>ACE</strong>s <strong>of</strong>ten need to communicate with one another or with a managing application<br />
for various reasons. For example:<br />
l<br />
l<br />
l<br />
<strong>ACE</strong>s can send alerts or status reports to the managing application.<br />
<strong>ACE</strong>s in a data processor module can receive control messages and data from<br />
<strong>ACE</strong>s in a control module.<br />
<strong>ACE</strong>s can send occasional packet data to other <strong>ACE</strong>s for special processing, or can<br />
exchange messages among themselves to coordinate packet processing.<br />
Because <strong>ACE</strong>s and their managing application might be running on different platforms<br />
and be written in different languages, the OMS acts as a message broker, using<br />
a remote procedure call model for object communication.<br />
<strong>ACE</strong>s and tasks communicate using a crosscall interface for remote method invocation.<br />
Remote method calls are handled through the distributed OMS, which provides<br />
marshalling and format conversion to address differences in byte order and word<br />
size between different processors.<br />
An <strong>ACE</strong> or task can act as a server or a client for remote procedure calls.<br />
l<br />
l<br />
The call server contains a crosscall object with the call method implementation.<br />
The call client makes remote calls to the call server using a crosscall reference object.<br />
12 Introduction and Overview<br />
Revision 3.3, August 2001
OMS for Global Application Services<br />
rules<br />
actions<br />
Remote<br />
procedure<br />
call<br />
CAP, crosscall reference<br />
OMS Communication Controller<br />
Client <strong>ACE</strong><br />
Packet<br />
flow<br />
Packet<br />
classification<br />
CAP, crosscall<br />
Response<br />
(optional)<br />
Related<br />
actions<br />
Server <strong>ACE</strong><br />
You define a crosscall interface for an application using an interface definition<br />
language, <strong>IXA</strong> IDL, that is provided with the <strong>IXA</strong> <strong>SDK</strong>. <strong>IXA</strong> IDL is not OMG IDL; it<br />
has been refined to specifically target the type <strong>of</strong> interfaces needed in network packet<br />
processing applications, rather than interfaces for general purpose applications.<br />
You define calls to be synchronous or asynchronous, with or without a response. The<br />
definition compiles to C code that implements the crosscall infrastructure, which you<br />
then modify to provide specific call functions.<br />
l<br />
l<br />
Modify the crosscall source file to implement application-specific call functions.<br />
Compile the source code into the call server executable.<br />
For asynchronous calls with response (deferred calls), modify the callback source<br />
file to implement the callback function that is executed when the call completes.<br />
Compile the source code for the crosscall references (stubs) and callbacks into the<br />
call client executable.<br />
Library <strong>ACE</strong>s and system <strong>ACE</strong>s typically export crosscall interfaces. <strong>ACE</strong>s defined in<br />
your application must import these interfaces and include the crosscall references in<br />
order to invoke the calls in the predefined <strong>ACE</strong>s.<br />
Micro<strong>ACE</strong><br />
Resource<br />
Manager<br />
Programs running on the core processor, including the core components <strong>of</strong> micro-<br />
<strong>ACE</strong>s and <strong>ACE</strong> management applications, communicate with the microengines<br />
using the micro<strong>ACE</strong> Resource Manager. The Resource Manager is system s<strong>of</strong>tware<br />
that runs in the core processor kernel. The Resource Manager API allows a micro<strong>ACE</strong><br />
management program to do the following:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Initialize and configure the IXP1200.<br />
Load code onto microengines.<br />
Enable and disable the microengines.<br />
Get and set the microengine configuration and resource assignments.<br />
Allocate and access uncached SRAM, SDRAM and scratch memory.<br />
Introduction and Overview 13<br />
Revision 3.3, August 2001
Hardware Architecture: The IXP1200 Network Processor<br />
l<br />
l<br />
Create and bind micro<strong>ACE</strong>s.<br />
Send packets to and receive packets from the microengines.<br />
Details <strong>of</strong> the Resource Manager API are provided in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Hardware Architecture: The IXP1200 Network Processor<br />
<strong>IXA</strong> applications run on the <strong>Intel</strong> IXP1200 network processor. The IXP1200 contains<br />
a StrongARM * core processor, a set <strong>of</strong> programmable microengines, onboard SDRAM<br />
and SRAM, and a high-speed bus.<br />
l<br />
l<br />
The StrongARM core processor is a general-purpose processor running an<br />
embedded Linux operating system. Conventional <strong>ACE</strong>s run on the core<br />
processor.<br />
The microengines are very high-speed processors that are specialized for packet<br />
processing. Micro<strong>ACE</strong>s run in microengines. Because there are no OMS services<br />
in the microengines, a component runs on the core processor to handle communications<br />
and control functions for micro<strong>ACE</strong>s.<br />
The <strong>Intel</strong> IXDP1200 Advanced Development Platform incorporates the IXP1200 into<br />
a board that has sixteen Ethernet 10/100 ports and two gigabit ports.<br />
IXM1200 Network<br />
Processor Base Card<br />
Single-Board<br />
Computer<br />
IXP1200<br />
Network<br />
Processor<br />
StrongARM<br />
Microengines<br />
S<strong>of</strong>tware<br />
Configuration<br />
Your s<strong>of</strong>tware environment includes the following:<br />
l<br />
l<br />
The IXP1200 embedded operating system is Linux.<br />
You must download the RAMdisk and Linux kernel onto the IXM1200 Network<br />
Processor Base Card.<br />
Your development environment is a combination <strong>of</strong> the Windows NT operating<br />
system and either a Linux platform or Cygwin for a Linux environment on the<br />
Windows NT platform, with the following development tools:<br />
— Microengine toolchain: Embedded Linux version <strong>of</strong> the IXP1200 Microengine<br />
Development Environment, running under Windows NT.<br />
This enables you to remotely develop and debug code running on<br />
Microengines on the IXP1200. You must install this from Volume II, CD 1.<br />
— StrongARM toolchain: GNU/C++ cross-hosted toolchain. You can invoke the<br />
toolchain utilities from a command shell or through the optional Embedded<br />
Linux IDE.<br />
14 Introduction and Overview<br />
Revision 3.3, August 2001
Hardware Architecture: The IXP1200 Network Processor<br />
This enables you to remotely develop and debug code running on the<br />
StrongARM on the IXP1200. You must install this from Volume II, CD 1.<br />
— Omni-NFS Server, optional.<br />
A 30-day trial version <strong>of</strong> an NFS server that makes directories located on a<br />
Windows NT platform visible to application code running on the StrongARM<br />
core processor. To use this optional s<strong>of</strong>tware, you must install this from<br />
Volume II CD 1.<br />
— Linux IDE, optional.<br />
This supports application development, kernel debugging, and device driver<br />
development. It includes VMON as its debugger and boot loader. To use this<br />
optional s<strong>of</strong>tware, you must install it from the Embedded Linux IDE CD-ROM<br />
Figure 1: Linux s<strong>of</strong>tware configuration for the <strong>Intel</strong> IXDP1200 Advanced Development<br />
Platform using only a Windows NT development environment<br />
IXM1200 Network<br />
Processor Base Card<br />
Windows NT<br />
platform<br />
Linux<br />
Microengine Toolchain:<br />
IXP1200 Microengine Development Environment<br />
StrongARM Toolchain:<br />
GNU C/C++ cross-compiler<br />
Linux IDE (optional)<br />
Figure 2: Linux s<strong>of</strong>tware configuration for the <strong>Intel</strong> IXDP1200 Advanced Development<br />
Platform using both Windows NT and Linux development environments<br />
IXM1200 Network<br />
Processor Base Card<br />
Windows NT<br />
platform<br />
Linux<br />
Microengine Toolchain:<br />
IXP1200 Microengine Development Environment<br />
StrongARM Toolchain:<br />
GNU C/C++ cross-compiler<br />
Linux IDE (optional)<br />
Linux<br />
platform<br />
Hardware<br />
Configuration<br />
To develop applications for the Embedded Linux environment using this release <strong>of</strong><br />
the <strong>IXA</strong> <strong>SDK</strong>, you must have one <strong>of</strong> the hardware configurations described in the <strong>IXA</strong><br />
<strong>SDK</strong> Installation and Setup Guide. There are three supported configurations for developers<br />
using Linux as the embedded operating system:<br />
l<br />
Configuration 1: Windows NT on the single-board computer on the <strong>Intel</strong><br />
IXDP1200 Advanced Development Platform with an external keyboard and<br />
monitor attached.<br />
Introduction and Overview 15<br />
Revision 3.3, August 2001
Hardware Architecture: The IXP1200 Network Processor<br />
IXM1200 Network<br />
Processor Base Card<br />
Single-board<br />
Computer<br />
Keyboard cable<br />
Serial<br />
Video cable<br />
Ethernet (see section on Ethernet connections)<br />
l<br />
Configuration 2: An external Windows NT workstation <strong>of</strong> your own choosing, in<br />
which case the single-board computer is not used.<br />
IXM1200 Network<br />
Processor Base Card<br />
Windows NT Workstation<br />
Serial<br />
Ethernet (see section on Ethernet connections)<br />
l<br />
Configuration 3: An external Linux workstation <strong>of</strong> your own choosing in addition<br />
to Windows NT on the single-board computer.<br />
IXM1200 Network<br />
Processor Base Card<br />
Single-board<br />
Computer<br />
Serial<br />
Keyboard cable<br />
Video cable<br />
Ethernet (see section on Ethernet connections)<br />
Linux workstation<br />
The connections in these configurations include:<br />
l<br />
A serial cable from the serial port <strong>of</strong> the IXM1200 Network Processor Base Card<br />
to the com port <strong>of</strong> the Windows NT platform to provide a remote serial console for<br />
the IXM1200 Network Processor Base Card.<br />
16 Introduction and Overview<br />
Revision 3.3, August 2001
Components <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> for the IXP1200<br />
l<br />
l<br />
Ethernet connections between the IXM1200 Network Processor Base Card and<br />
your chosen Windows NT and/or Linux development platforms as described in<br />
the <strong>IXA</strong> <strong>SDK</strong> Installation and Setup Guide.<br />
For remote debugging <strong>of</strong> the IXM1200 Network Processor Base Card, all configurations<br />
use the Ethernet connection.<br />
In configurations 1 and 3, video and keyboard cables from the single-board<br />
computer to your own external monitor and keyboard.<br />
Deploying<br />
Applications<br />
Most developers <strong>of</strong> <strong>IXA</strong> systems develop hardware and s<strong>of</strong>tware simultaneously:<br />
l<br />
l<br />
OEMs develop boards and systems around the IXP1200 chip.<br />
Appliance vendors develop systems around an <strong>Intel</strong> board, the Policy Accelerator,<br />
which contains a complete IXP1200 subsystem.<br />
At the beginning <strong>of</strong> the development cycle, s<strong>of</strong>tware developers work with a generic<br />
development system. Later in the development cycle, the s<strong>of</strong>tware and hardware<br />
developers work together to integrate the s<strong>of</strong>tware into the deployment hardware<br />
environment.<br />
To deploy an <strong>IXA</strong> application, you use the RAMdisk and flash utilities to create a<br />
flash image that contains both the application code you developed and an embedded<br />
Linux operating system. Depending on your deployment configuration, you download<br />
this image to the flash in the IXP1200 in the factory, or create an initialization or<br />
boot procedure to download it.<br />
Components <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> for the IXP1200<br />
The <strong>IXA</strong> <strong>SDK</strong> is designed specifically to develop <strong>IXA</strong> applications. It contains the<br />
tools, libraries, drivers, and other runtime elements that you use to develop, debug,<br />
and deliver embedded network applications. It also contains efficient languages for<br />
describing and classifying packets and for defining communication interfaces.<br />
The <strong>IXA</strong> <strong>SDK</strong> includes the following elements:<br />
l<br />
An application programming interface, the <strong>IXA</strong> API, which includes the<br />
following:<br />
— Object Management System (OMS) services library, which provides C support<br />
for interobject communication, <strong>ACE</strong> creation, and control <strong>of</strong> traffic flow.<br />
— The Action Services Library (ASL) core services, which provide C and C++<br />
support for the packet-handling mechanism, and C support for data sets,<br />
event scheduling, and error handling.<br />
— The ASL application services, independent libraries which provide C and C++<br />
support for efficient implementation <strong>of</strong> common packet-manipulation tasks,<br />
such as TCP/IP manipulation and reassembly, NAT, string searches in<br />
packets, ARP processing, and so on. These application building blocks speed<br />
development time. Additional libraries are made available from time to time.<br />
— The micro<strong>ACE</strong> Resource Manager API, which provides management services<br />
for micro<strong>ACE</strong>s and microengines and access to shared memory.<br />
Introduction and Overview 17<br />
Revision 3.3, August 2001
Components <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> for the IXP1200<br />
— Microcode macros for use in micro<strong>ACE</strong> microblocks and dispatch loops.<br />
l<br />
l<br />
l<br />
System s<strong>of</strong>tware, which includes the following:<br />
— The <strong>ACE</strong> runtimes for each <strong>ACE</strong>, which perform packet handling<br />
— The Object Management System (OMS), which acts as a name server and<br />
resource manager and provides the framework for interobject communication<br />
— The micro<strong>ACE</strong> Resource Manager, which manages micro<strong>ACE</strong> memory and<br />
coordinates communication between the core component and microblock in<br />
micro<strong>ACE</strong>s.<br />
— An embedded operating system (Linux, a widely-used, standard, open-source<br />
system)<br />
— A boot manager that performs power-on initialization<br />
— Device drivers<br />
— A TCP/IP protocol stack<br />
— Run-time libraries that provide execution and management services for the<br />
<strong>ACE</strong> model, name space, data handling, and interobject communication.<br />
S<strong>of</strong>tware development tools:<br />
— Network Classification Language (NCL), which you use to classify packets<br />
and direct actions to be taken.<br />
— An interface definition language, <strong>IXA</strong> IDL, in which you specify the crosscall<br />
interfaces that objects use to communicate through the OMS.<br />
— Linux compilers, assemblers, linkers, loaders, and debuggers for code in the<br />
various languages (C/C++, IDL, and NCL).<br />
— Command-line utilities for working with <strong>ACE</strong>s.<br />
— The IXP1200 Microengine Development Environment, a tool that supports the<br />
development and integration <strong>of</strong> microcode modules targeted for the microengines,<br />
the optimized packet processors on the IXP1200. This includes<br />
IXP1200 microcode, along with compilers, debuggers, and application development<br />
utilities.<br />
Predefined building blocks<br />
Example code and sample applications, reusable and modifiable library <strong>ACE</strong>s,<br />
predefined protocol descriptions, and other elements to make application development<br />
rapid.<br />
18 Introduction and Overview<br />
Revision 3.3, August 2001
Chapter 2<br />
Elements <strong>of</strong> an Application<br />
This chapter introduces the languages and libraries that you use to build networking<br />
applications with the <strong>Intel</strong> ® <strong>IXA</strong> <strong>SDK</strong>. It describes the <strong>IXA</strong> system s<strong>of</strong>tware that coordinates<br />
objects running on different processors, the C structures that support the <strong>ACE</strong><br />
model, and the application building process.<br />
This chapter contains the following topics:<br />
l “Overview” on page 19<br />
l “The Object Management System” on page 20<br />
l “<strong>ACE</strong>s and Support Structures” on page 22<br />
l “Micro<strong>ACE</strong> Support Services” on page 24<br />
l “The Application Building Process” on page 25<br />
Overview<br />
The <strong>IXA</strong> <strong>SDK</strong> defines the active computing element (<strong>ACE</strong>), and provides an infrastructure<br />
and object-oriented environment that you use to develop applications using<br />
the <strong>ACE</strong> programming framework.<br />
Your application creates C structures and C++ objects for each independent <strong>ACE</strong>, and<br />
additional code in supporting languages such as Network Classification Language<br />
(NCL), <strong>IXA</strong> Interface Definition Language (IDL), and IXP1200 microcode. Each <strong>ACE</strong><br />
can call API functions or predefined macros, as well as defining functions to perform<br />
the network service functionality that your application requires.<br />
The <strong>IXA</strong> <strong>SDK</strong> includes tools for programming the IXP1200 directly in microcode<br />
(assembly language), and also provides the infrastructure for integrating microcode<br />
with <strong>ACE</strong>s using the micro<strong>ACE</strong> architecture.<br />
Revision 3.3, August 2001<br />
Elements <strong>of</strong> an Application 19
The Object Management System<br />
A networking application that uses the <strong>ACE</strong> programming framework makes use <strong>of</strong><br />
function libraries, macros, and so on that are provided with the <strong>SDK</strong>. Such an application<br />
includes source code in the following languages:<br />
Language Tools Libraries and predefined code<br />
C/C++<br />
Gnu toolchain (gcc, ld,<br />
gdb, and so on)<br />
Object Management System<br />
(OMS), Action Services Library<br />
(ASL), Resource Manager, startup<br />
and configuration scripts<br />
IXP1200 microcode<br />
IXP1200 Microengine<br />
Development Environment<br />
IXP1200 packet-handling macros,<br />
micro<strong>ACE</strong> macros<br />
Network Classification<br />
Language (NCL)<br />
<strong>IXA</strong> Interface Definition<br />
Language (IDL)<br />
NCL compiler (nclcomp)<br />
<strong>IXA</strong> IDL compiler<br />
(tao_idl)<br />
TCP/IP protocol definitions<br />
The <strong>IXA</strong> <strong>SDK</strong> provides entire predefined <strong>ACE</strong>s that you can use as building blocks<br />
for rapid application development. These include the following:<br />
l<br />
l<br />
l<br />
The interface <strong>ACE</strong>s, system-defined micro<strong>ACE</strong>s that every application uses to<br />
receive and transmit packets on the network interface ports<br />
The stack <strong>ACE</strong>, which represents the Linux * TCP/IP stack<br />
Several library <strong>ACE</strong>s that perform typical networking tasks such as layer-three<br />
packet forwarding, layer-two bridging, and network address translation.<br />
For more information on the predefined <strong>ACE</strong>s, see Chapter 7, “Interface <strong>ACE</strong>s,” and<br />
Chapter 8, “Stack and Library <strong>ACE</strong>s.”<br />
The Object Management System<br />
The Object Management System (OMS), part <strong>of</strong> the IX system s<strong>of</strong>tware, is a single<br />
logical entity with components distributed throughout the system. The OMS services<br />
are part <strong>of</strong> the <strong>IXA</strong> API. The management and control modules for an application use<br />
the global C functions defined by the OMS services to create, configure, control, and<br />
destroy objects and structures in all parts <strong>of</strong> the application, and to perform global<br />
tasks. The primary global services your application requires are:<br />
l<br />
l<br />
l<br />
Creating and destroying <strong>ACE</strong>s<br />
Defining and controlling packet flow using targets<br />
Communicating among <strong>ACE</strong>s and other programs with crosscalls<br />
Parts <strong>of</strong> the<br />
OMS<br />
The OMS contains the following parts:<br />
l<br />
The Resolver, which creates and deletes <strong>ACE</strong>s, and manages packet flow by<br />
binding <strong>ACE</strong>s and targets.<br />
20 Elements <strong>of</strong> an Application<br />
Revision 3.3, August 2001
The Object Management System<br />
l<br />
The Name Server, which manages the name space for the OMS, maintaining a<br />
correspondence between names and internal identifiers for <strong>ACE</strong>s, targets and so<br />
on. The name space allows objects that might be distributed among processors to<br />
address one another unambiguously.<br />
The OMS also defines some general global functions to coordinate interobject<br />
communication through crosscalls.<br />
You typically set up both the development and delivery environments to start the<br />
OMS automatically on boot, so that it is always running.<br />
Accessing the<br />
OMS<br />
In order to communicate with the OMS, an object or program must create a communications<br />
channel in the form <strong>of</strong> a separate process or thread called a communication<br />
access process, or CAP.<br />
l<br />
l<br />
When you create an <strong>ACE</strong>, the initialization procedure automatically creates the<br />
CAP, and the <strong>ACE</strong> runtime polls that CAP for crosscall events in its main loop.<br />
You can access the CAP with the function ix_ace_to_cap.<br />
If your application contains other programs that need to communicate with the<br />
OMS (a manager program, for example), each such object must register with the<br />
OMS as a task. The task, like an <strong>ACE</strong>, contains a CAP, which you can access with<br />
the function ix_task_to_cap. The task’s main loop must poll for crosscall events<br />
on the CAP channel.<br />
Before you can create an <strong>ACE</strong> or task, you must create a CAP with which to make the<br />
Resolver calls. To create a CAP, use the ASL function ix_cap_init. Any application<br />
that needs to communicate with the OMS must include the ASL core services library,<br />
as well as the OMS services library, even if it does not use any ASL functions other<br />
than ix_cap_init.<br />
Naming<br />
Objects<br />
The Name Server provides a name space, which allows objects that might be distributed<br />
among processors to address one another unambiguously. The Name Server<br />
supports a hierarchical UNIX-like directory structure. The name <strong>of</strong> a target (for<br />
example) needs to be unique only within an <strong>ACE</strong>, and the name <strong>of</strong> the <strong>ACE</strong> needs to<br />
be unique only within an application-defined directory.<br />
To completely and uniquely identify an entity to the Name Server, you must use the<br />
full name, or complete path to the entity. You use the full name whenever you refer to<br />
an object using the OMS services. For example, a call to ix_res_bind must specify<br />
the full name <strong>of</strong> both the target and the <strong>ACE</strong>.<br />
For example, to create a binding between the default target in an <strong>ACE</strong> named MyAce<br />
and an <strong>ACE</strong> named ControlAce, in an application with no other name space directories<br />
defined, use the following full names in the ix_res_bind method:<br />
ix_res_bind (ressession, "/MyAce/default" , "/ControlAce");<br />
For More<br />
Information<br />
l<br />
For more information on targets and bindings, see Chapter 5, “Controlling Packet<br />
Flow.”<br />
Revision 3.3, August 2001<br />
Elements <strong>of</strong> an Application 21
<strong>ACE</strong>s and Support Structures<br />
l<br />
l<br />
For more information on crosscalls, see Chapter 11, “Communication Within an<br />
Application.”<br />
For detailed reference information on OMS functions, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
<strong>ACE</strong>s and Support Structures<br />
The primary processing element on an <strong>IXA</strong> application is the <strong>ACE</strong>. An application<br />
can contain multiple <strong>ACE</strong>s to perform different processing operations, can start and<br />
stop <strong>ACE</strong>s at run time, and can change how packets flow from ports, through <strong>ACE</strong>s,<br />
and out <strong>of</strong> ports.<br />
The <strong>IXA</strong> <strong>SDK</strong> defines system <strong>ACE</strong>s to represent the physical network interfaces and<br />
the Linux TCP/IP stack, and library <strong>ACE</strong>s to perform typical network processing<br />
tasks. You define additional <strong>ACE</strong>s to process packets as needed by your application.<br />
Creating <strong>ACE</strong>s<br />
To define and create an <strong>ACE</strong>, you must first create the <strong>ACE</strong> single object executable.<br />
To do this:<br />
1. Define the <strong>ACE</strong>’s initialization phase in a C source file. This file must contain a<br />
definition for the initialization function ix_init. This function definition must, at<br />
least, allocate an <strong>ACE</strong> structure (ix_ace) and call ix_ace_init, which creates the<br />
<strong>ACE</strong> object. The function should also create and initialize any other structures<br />
that belong to the <strong>ACE</strong>, such as targets and sets. The file must also define a corresponding<br />
termination function (ix_fini) that cleans up the created structures.<br />
2. Define the <strong>ACE</strong>’s action phase in a C source file. The action code must contain<br />
definitions for the <strong>ACE</strong>’s action functions, which implement the handling and<br />
disposition <strong>of</strong> classified packets.<br />
3. Define the crosscall interfaces for interobject communication in an <strong>IXA</strong> IDL source<br />
file, compile it with the tao_idl compiler. This results in additional C source files<br />
for the <strong>ACE</strong>. See “Supporting Languages” on page 23.<br />
4. Define the <strong>ACE</strong>’s classification phase in an NCL source file. See “Supporting<br />
Languages” on page 23.<br />
5. Compile and link the initialization, action, and classification code into a single<br />
executable. (See Chapter 3, “Compiling and Testing Applications.”)<br />
An application’s manager program can create and initialize the application’s <strong>ACE</strong>s<br />
by calling Resolver functions in the OMS. To do this, it must first create a CAP<br />
channel through which to communicate with the Resolver. In the manager program:<br />
1. Create a CAP channel to the OMS using the ASL function ix_cap_init.<br />
2. Open a Resolver session by passing the CAP to the OMS function ix_res_open.<br />
3. Create the <strong>ACE</strong> using the function ix_res_create_ace, passing the Resolver<br />
session handle, the name <strong>of</strong> the <strong>ACE</strong>, and the path to the <strong>ACE</strong> executable in the<br />
development file system.<br />
You can also create <strong>ACE</strong>s from the command line or a script using the utility ixace.<br />
This utility creates a Resolver session and calls the ix_res_create_ace function.<br />
22 Elements <strong>of</strong> an Application<br />
Revision 3.3, August 2001
<strong>ACE</strong>s and Support Structures<br />
To create the <strong>ACE</strong>, the Resolver calls the initialization function you have defined in<br />
the <strong>ACE</strong> executable, and starts the <strong>ACE</strong>’s main loop, which polls continuously for<br />
packet arrival events and crosscall events.<br />
Support<br />
Objects<br />
The following table shows the C structures that can be part <strong>of</strong> an <strong>ACE</strong>.<br />
ASL structure<br />
Description<br />
ix_target<br />
ix_base_t<br />
ix_set<br />
ix_element<br />
ix_event<br />
ix_time<br />
Represents a packet destination target. You define targets<br />
in each <strong>ACE</strong> for all possible packet destinations. Each<br />
<strong>ACE</strong> is automatically initialized with one target, named<br />
default.<br />
l For more information, see Chapter 5, “Controlling<br />
Packet Flow.”<br />
Represents a crosscall interface. You must initialize each<br />
crosscall interface with this structure in both the server<br />
and the client before making any remote calls.<br />
l For more information, see Chapter 11, “Communication<br />
Within an Application.”<br />
Represents a data set, as defined in the <strong>ACE</strong>’s classification<br />
code.<br />
l For more information, see Chapter 13, “Using Sets <strong>of</strong><br />
Data to Classify Packets.”<br />
Represents a data set member element. You modify this<br />
structure to contain your application-specific data.<br />
l For more information, see Chapter 13, “Using Sets <strong>of</strong><br />
Data to Classify Packets.”<br />
Represents a schedulable event. You define a callback<br />
function to be executed when a specified time has<br />
elapsed.<br />
l For more information, see Chapter 10, “Initializing and<br />
Acting on Packets in an <strong>ACE</strong>.”<br />
Represents a time value for scheduling events.<br />
l For more information, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Additional<br />
Services<br />
Additional libraries extend the ASL to provide application services for TCP/IP<br />
packet manipulation. For more information, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Supporting<br />
Languages<br />
The <strong>IXA</strong> <strong>SDK</strong> includes two languages, Network Classification Language (NCL), and<br />
<strong>IXA</strong> Interface Definition Language (IDL), that you use to create some <strong>of</strong> the source<br />
code for an <strong>ACE</strong>.<br />
Elements <strong>of</strong> an Application 23<br />
Revision 3.3, August 2001
Micro<strong>ACE</strong> Support Services<br />
l<br />
l<br />
An <strong>ACE</strong> classifies incoming packets according to rules and protocol definitions<br />
that you write in NCL. For more information, see Chapter 9, “Classifying Packets<br />
Using NCL.”<br />
<strong>ACE</strong>s and other objects communicate using a remote procedure call mechanism<br />
called a crosscall. You define the interfaces for the crosscalls in <strong>IXA</strong> IDL. For more<br />
information, see Chapter 11, “Communication Within an Application.”<br />
Error Handling<br />
Most API functions return an error token, which is a value <strong>of</strong> type ix_error. An error<br />
token <strong>of</strong> zero indicates that the function was successful. When a call is unsuccessful,<br />
it returns a non-zero token that is associated with a descriptive string giving information<br />
about the failure.<br />
The ASL defines a set <strong>of</strong> functions for retrieving the messages associated with error<br />
tokens, and a set <strong>of</strong> macros that provide additional context information for errors. It<br />
also provides functions you can use to add your own uniquely numbered error codes<br />
to provide information about failed operations in your own functions.<br />
l<br />
l<br />
The error handling functions and macros are describe in Chapter 4, “The ASL<br />
Core Support Package API,” <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
The predefined error codes are listed and described in Appendix A, “<strong>IXA</strong> API<br />
Error Codes,” <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Micro<strong>ACE</strong> Support Services<br />
Conventional <strong>ACE</strong>s run on a general-purpose processor. To achieve higher performance,<br />
<strong>ACE</strong>s can use other special-purpose processors for acceleration. An <strong>ACE</strong> that<br />
<strong>of</strong>floads fast-path processing to an IXP1200 microengine is known as a micro<strong>ACE</strong>.<br />
A micro<strong>ACE</strong> combines a core component, a complete <strong>ACE</strong> that runs on the core<br />
processor, with a microblock.<br />
1. Write the microblock in microcode, the assembler language for the IXP1200<br />
microengines.<br />
2. Combine several microblocks with a dispatch loop, also in microcode, that defines<br />
a packet processing pipeline for a microblock group.<br />
3. Compile the microblocks and dispatch loop into a single-object image (a .u<strong>of</strong> file)<br />
that runs on a single microengine.<br />
To write and compile microcode, use the IXP1200 Microengine Development Environment.<br />
The IXP1200 microcode documentation is accessible from the following<br />
directory:<br />
C:IXP1200\documentation\IXP1200 Documentation<br />
Micro<strong>ACE</strong>s and their managing programs communicate with the microengines<br />
using the Resource Manager. The Resource Manager is system s<strong>of</strong>tware that runs in the<br />
core processor kernel. It does resource allocation for memory that is shared by the<br />
core processor and the microengines, and also handles packet demultiplexing and<br />
other system-level microengine management problems.<br />
24 Elements <strong>of</strong> an Application<br />
Revision 3.3, August 2001
The Application Building Process<br />
The Resource Manager defines a C-language API, which you can use in an <strong>ACE</strong><br />
management program or in <strong>ACE</strong> code to set up micro<strong>ACE</strong>s and manage the shared<br />
memory resources.<br />
The <strong>IXA</strong> <strong>SDK</strong> also defines a number <strong>of</strong> microcode macros that specifically support<br />
the micro<strong>ACE</strong> programming framework. Use these in the microblocks and the<br />
dispatch loop to define and access global variables in the shared memory, to manipulate<br />
packet buffers, and to pass packets between the microengine and the core<br />
processor.<br />
l<br />
For more information on micro<strong>ACE</strong>s and their supporting system s<strong>of</strong>tware, see<br />
Chapter 6, “Writing Micro<strong>ACE</strong>s.”<br />
The Application Building Process<br />
The following gives a rough picture <strong>of</strong> the process you use to define all <strong>of</strong> the parts<br />
<strong>of</strong> an <strong>IXA</strong> application, with references to places you can find more information on<br />
each piece.<br />
1. Define your services at a high level, and decide how to implement them with<br />
conventional <strong>ACE</strong>s, micro<strong>ACE</strong>s, and standard application programming.<br />
2. Sketch packet flow among the <strong>ACE</strong>s and decide what targets you will need and<br />
how to bind them.<br />
3. For the micro<strong>ACE</strong>s:<br />
a. Implement the microblocks for each micro<strong>ACE</strong> using the IXP1200<br />
Microengine Development Environment.<br />
b. Write a dispatch loop to implement the microcode packet pipeline for each<br />
microblock group.<br />
c. Create a microcode image for each microengine by compiling and linking the<br />
microblocks in each group (including those for the interface <strong>ACE</strong>s and library<br />
<strong>ACE</strong>s you are using) with the dispatch loop, using the IXP1200 Microengine<br />
Development Environment.<br />
For more information, see Chapter 6, “Writing Micro<strong>ACE</strong>s.”<br />
4. Implement the classification rules for each <strong>ACE</strong> in NCL.<br />
a. Define protocols and predicates. You can include the standard TCP/IP<br />
protocol, which is predefined and provided as part <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong>.<br />
b. Define data sets and searches. For more information, see Chapter 13, “Using<br />
Sets <strong>of</strong> Data to Classify Packets.”<br />
c. Define rules that call action functions. This will help you define the names and<br />
signatures <strong>of</strong> the action functions, which you will define later.<br />
For more information, see Chapter 9, “Classifying Packets Using NCL.”<br />
5. Implement action code for each <strong>ACE</strong> in C, defining the action functions called by<br />
the rules.<br />
For more information, see Chapter 10, “Initializing and Acting on Packets in an<br />
<strong>ACE</strong>.”<br />
Revision 3.3, August 2001<br />
Elements <strong>of</strong> an Application 25
The Application Building Process<br />
6. Define the crosscalls with which <strong>ACE</strong>s and the manager program will communicate:<br />
a. Define crosscall interfaces in <strong>IXA</strong> IDL.<br />
b. Compile the interface definitions with the <strong>IXA</strong> IDL compiler tao_idl. This<br />
produces a set <strong>of</strong> C headers and source files that define crosscalls and crosscall<br />
references.<br />
c. Edit the generated crosscall source to define the call methods.<br />
d. If needed, edit the generated callback sources to define callbacks for asynchronous<br />
calls.<br />
For more information, see Chapter 11, “Communication Within an Application.”<br />
7. Implement initialization code for each <strong>ACE</strong> in C.<br />
a. Define an initialization function to create the <strong>ACE</strong> and its related objects<br />
(targets, sets, and so on). See “Creating <strong>ACE</strong>s” on page 22.<br />
b. Define methods and utility functions.<br />
c. Include the crosscall headers as needed (depending on whether the <strong>ACE</strong> is<br />
acting as a call server or call client). Initialize each crosscall interface in both<br />
the server and the client. See Chapter 11, “Communication Within an Application.”<br />
8. Create the <strong>ACE</strong> executable for each <strong>ACE</strong>.<br />
a. Compile the NCL code using nclcomp, then gcc.<br />
b. Compile the action, initialization, and crosscall code using gcc.<br />
c. Link the rules object, action object, initialization object, and crosscall objects<br />
using ld.<br />
You typically use a makefile to do this. For more information, see Chapter 3,<br />
“Compiling and Testing Applications.”<br />
9. Modify the startup script’s configuration file, ixsys.config:<br />
a. Specify and configure the ports you are using.<br />
b. Create and start the micro<strong>ACE</strong>s, specifying a microcode image for each type<br />
<strong>of</strong> port.<br />
c. Create and start the conventional <strong>ACE</strong>s, passing in a pointer to the single<br />
object executable.<br />
d. Bind targets and <strong>ACE</strong>s to determine packet flow in the application.<br />
e. Run the configuration scripts for any library <strong>ACE</strong>s you are using.<br />
For more information, see Chapter 4, “Configuring and Starting <strong>IXA</strong> Systems.”<br />
10. Create a runtime, downloading the application and operating system to IXP1200<br />
flash. For the development system:<br />
a. Open a remote shell to the IXDP1200 Advanced Development Platform from<br />
the Linux development workstation.<br />
b. Mount the workstation’s NFS directory on the IXP200.<br />
26 Elements <strong>of</strong> an Application<br />
Revision 3.3, August 2001
The Application Building Process<br />
c. Copy all executables to the IXP1200’s NFS directory.<br />
11. Run the startup script, ixstart, from the command line <strong>of</strong> the remote shell.<br />
Elements <strong>of</strong> an Application 27<br />
Revision 3.3, August 2001
The Application Building Process<br />
28 Elements <strong>of</strong> an Application<br />
Revision 3.3, August 2001
Chapter 3<br />
Compiling and Testing Applications<br />
This chapter describes each <strong>of</strong> the compilation steps in detail to help you understand<br />
the compilation model for <strong>ACE</strong>s and <strong>IXA</strong> applications.<br />
This chapter contains the following topics:<br />
l “Overview <strong>of</strong> the <strong>ACE</strong> Compilation and Linking Process” on page 29<br />
l “Compiling Micro<strong>ACE</strong>s” on page 32<br />
l “Using Makefiles” on page 33<br />
l “Debugging an Application” on page 33<br />
Overview <strong>of</strong> the <strong>ACE</strong> Compilation and Linking Process<br />
To create an <strong>ACE</strong> single-object executable file, you compile and link several source<br />
files using the GNU tools, NCL compiler, and <strong>IXA</strong> IDL compiler. Source files include:<br />
l<br />
l<br />
l<br />
C/C++ files for initialization code and action functions<br />
NCL files for classification rules<br />
<strong>IXA</strong> IDL files for crosscall interfaces, which compile to additional C files for the<br />
crosscall source code<br />
Your application uses makefiles and scripts to ensure that all <strong>of</strong> an application’s files<br />
are compiled, linked, and loaded in the correct manner and order.<br />
A micro<strong>ACE</strong> has, in addition to these <strong>ACE</strong> source files that define the core component,<br />
a microcode source file that defines the microblock. See “Compiling<br />
Micro<strong>ACE</strong>s” on page 32.<br />
Intermediate<br />
Compilation<br />
A conventional <strong>ACE</strong> contains rules written in NCL. Compile the NCL file to an intermediate<br />
.s file using the NCL compiler, nclcomp. Compile the intermediate file to a<br />
.o linkable object with the GNU C/C++ compiler, gcc.<br />
Compiling and Testing Applications 29<br />
Revision 3.3, August 2001
Overview <strong>of</strong> the <strong>ACE</strong> Compilation and Linking Process<br />
The names <strong>of</strong> all cross-compilation utilities are prefixed with target platform information.<br />
For the StrongARM * core processor on the IXP1200, the prefix is armv4bunknown-linux-.<br />
For example, to create an executable for an <strong>ACE</strong> to run on the core<br />
processor, use the cross compiler armv4b-unknown-linux-gcc.<br />
When using crosscalls, you must provide crosscall interfaces written in <strong>IXA</strong> IDL.<br />
Compile .idl source files to .c and .h files using the IDL compiler, tao_idl. Include<br />
the header files as needed in the <strong>ACE</strong> initialization code source, depending on<br />
whether the <strong>ACE</strong> acts as a crosscall server or client. (See Chapter 11, “Communication<br />
Within an Application.”) Compile and link the crosscall source files into the <strong>ACE</strong><br />
executable, using gcc and ld.<br />
l<br />
l<br />
For a crosscall server, link in the crosscall source file.<br />
For a crosscall client, link in the stub (crosscall reference) source file, and, if there<br />
are deferred calls, the callback source file.<br />
Compiling and<br />
Linking Source<br />
Files<br />
A conventional <strong>ACE</strong> contains initialization code written in C/C++, which creates<br />
and initializes the <strong>ACE</strong> object and related structure, and action code written in C,<br />
which defines the action functions. Compile the source files for both these parts into<br />
.o linkable objects using the GNU C/C++ compiler, gcc.<br />
Finally, link the rules, action, and initialization objects into a single object <strong>ACE</strong><br />
executable file, using the GNU linker, ld. When you create the <strong>ACE</strong> (using either the<br />
Resolver ix_res_create_ace function in a management program or the ace<br />
keyword in a system configuration file), you specify the path to this executable. See<br />
Chapter 4, “Configuring and Starting <strong>IXA</strong> Systems.”<br />
The following figure shows the general flow <strong>of</strong> application files through the compilation<br />
process.<br />
30 Compiling and Testing Applications<br />
Revision 3.3, August 2001
Overview <strong>of</strong> the <strong>ACE</strong> Compilation and Linking Process<br />
Manager<br />
program<br />
C code<br />
mgr.c<br />
stub.c<br />
ASL<br />
gcc, ld<br />
mgr.o<br />
<strong>IXA</strong> IDL code<br />
ccif.idl<br />
tao_idl<br />
<strong>ACE</strong><br />
code<br />
NCL code<br />
rules.ncl<br />
C code<br />
actions.c<br />
init.c<br />
cc.c<br />
ASL<br />
nclcomp<br />
gcc<br />
rules.s<br />
rules.o<br />
actions.o<br />
init.o<br />
cc.o<br />
ld<br />
ace.o<br />
For more information on options available during compilation and linking, see:<br />
l Chapter 7, “Command-Line Tools,” in the <strong>IXA</strong> <strong>SDK</strong> Reference<br />
l Publicly available GNU C/C++ tool documentation<br />
Compiling<br />
Kernel <strong>ACE</strong>s<br />
During development, all conventional <strong>ACE</strong>s run in user space, so that you can test<br />
and debug them. When you deliver an application, however, you can choose to run<br />
a conventional <strong>ACE</strong> that is in the critical path in kernel space for maximum performance.<br />
If you intend to compile an <strong>ACE</strong> for the kernel, you must write it entirely in<br />
C, not C++.<br />
Although conventional <strong>ACE</strong>s generally do exception processing, while micro<strong>ACE</strong>s<br />
handle fast-path packet processing, some kinds <strong>of</strong> exception processing are more critical<br />
than others. For example, an <strong>ACE</strong> that processes new TCP sessions would need<br />
to be optimized for performance, while one that counts errors would not affect the<br />
overall efficiency <strong>of</strong> the application.<br />
Compiling and Testing Applications 31<br />
Revision 3.3, August 2001
Compiling Micro<strong>ACE</strong>s<br />
Compiling Micro<strong>ACE</strong>s<br />
A micro<strong>ACE</strong> contains a core component, for which you build a single-object<br />
executable in the same way as for a conventional <strong>ACE</strong>. In addition, each<br />
micro<strong>ACE</strong> contains a microblock. The source for the microblock can be:<br />
l<br />
l<br />
A microcode .uc file.<br />
A Micro C file compiled to microcode.<br />
You define a microblock group to run on each microengine and write a microcode<br />
dispatch loop to define the packet processing pipeline in the group. Use<br />
the IXP1200 Microengine Development Environment to compile and link all <strong>of</strong><br />
the microblocks in the group, together with the microcode file for the dispatch<br />
loop, into a microcode image (.u<strong>of</strong> file) for a single microengine.<br />
You must specify the microcode image to be used for each type <strong>of</strong> port, such as<br />
10/100BaseT Ethernet input or gigabit Ethernet output. To do this, you can<br />
modify the startup script’s configuration file (ixsys.config), or use the<br />
Resource Manager function RmUengSetUcode as part <strong>of</strong> your own <strong>ACE</strong> initialization<br />
and management program. You can run the same image on more than<br />
one microengine, or different images on each. The Resource Manager allocates<br />
the threads on the microengines.<br />
The type <strong>of</strong> a microcode image is determined as shown in the following table:<br />
Type<br />
Slow ingress<br />
Slow egress<br />
Fast ingress<br />
Fast egress<br />
Other<br />
Description<br />
The image contains the microblock for the input interface <strong>ACE</strong>, configured<br />
for 10/100BaseT ports.<br />
The image contains the microblock for the output interface <strong>ACE</strong>, configured<br />
for 10/100BaseT ports.<br />
The image contains the microblock for the input interface <strong>ACE</strong>, configured<br />
for gigabit ports.<br />
The image contains the microblock for the output interface <strong>ACE</strong>, configured<br />
for gigabit ports.<br />
The image does not contain an interface <strong>ACE</strong> microblock.<br />
l For more information on writing and starting micro<strong>ACE</strong>s, see Chapter 4,<br />
“Configuring and Starting <strong>IXA</strong> Systems,” and Chapter 6, “Writing<br />
Micro<strong>ACE</strong>s.”<br />
l<br />
For more information on creating and configuring interface <strong>ACE</strong>s, see<br />
Chapter 7, “Interface <strong>ACE</strong>s.”<br />
32 Compiling and Testing Applications<br />
Revision 3.3, August 2001
Using Makefiles<br />
l<br />
The microengine toolchain and the IXP1200 Microengine Development Environment<br />
are documented in the IXP1200 documentation set.<br />
Using Makefiles<br />
The UNIX make utility provides the most effective way to ensure that all <strong>of</strong> an application’s<br />
files are compiled and linked in the correct manner and order.<br />
You can issue compilation and linking commands directly from the command line in<br />
a command shell, but you typically use a makefile to compile and link your application.<br />
Makefiles are designed to handle dependencies in compilation order and variations<br />
in the names and locations <strong>of</strong> tools and source files.<br />
For information on compilation and linking options, see:<br />
l Chapter 7, “Command-Line Tools,” in the <strong>IXA</strong> <strong>SDK</strong> Reference<br />
l<br />
Publicly available GNU C/C++ tool documentation<br />
Debugging an Application<br />
Use the GNU debugger, gdb, to test and debug your <strong>IXA</strong> application. This debugging<br />
tool is provided as part <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> distribution.<br />
You can use GDB on your x86 Linux * host to remotely debug applications running on<br />
the IXDP1200 Advanced Development Platform. For example, to debug a file<br />
myfile.c:<br />
1. Compile myfile.c with the big-endian ARM * toolchain version <strong>of</strong> gcc with the -<br />
g option.<br />
2. Open a remote shell for the IXP1200 on the Linux host using Minicom, or on a<br />
Windows NT * host using Hyperterm.<br />
3. Transfer the binary for myfile into the RAMdisk <strong>of</strong> the IXP1200 using FTP or NFS.<br />
4. In a command shell for the IXP1200, type:<br />
gdbserver hostip_addr:port_number myfile arguments<br />
For example:<br />
gdbserver 10.3.19.128:12345 myfile<br />
5. On the host, go to the source directory for myfile, then start GDB on the file:<br />
cd /mydir<br />
gdb myfile<br />
NOTE:<br />
You can use the front-end GUI provided by Red Hat. To do this, invoke GDB<br />
with xxgdb myfile, rather than gdb myfile.<br />
Compiling and Testing Applications 33<br />
Revision 3.3, August 2001
Debugging an Application<br />
6. At the GDB prompt, connect to the IXP1200 target:<br />
target remote IXP1200_ipaddr:port_number<br />
7. At this point, the program is running and you can begin using the debugger.<br />
— Type list to see the code.<br />
— After setting a breakpoint, type continue (not run).<br />
For more information on how to use GDB, see publicly available GNU tool documentation.<br />
34 Compiling and Testing Applications<br />
Revision 3.3, August 2001
Chapter 4<br />
Configuring and Starting <strong>IXA</strong> Systems<br />
This chapter describes how to start an <strong>IXA</strong> system with a particular port configuration<br />
and launch the application’s system <strong>ACE</strong>s, library <strong>ACE</strong>s, and user <strong>ACE</strong>s.<br />
This chapter contains the following topics:<br />
l “Overview” on page 35<br />
l “Using Startup Scripts and Configuration Files” on page 36<br />
l “The System Configuration File” on page 37<br />
l “Setting Up Particular Configurations” on page 39<br />
l “Launching Application <strong>ACE</strong>s” on page 46<br />
Overview<br />
Typically, you start the system s<strong>of</strong>tware automatically as part <strong>of</strong> booting the<br />
IXDP1200 Advanced Development Platform. To do this, you call a startup script,<br />
which in turn calls other scripts. The scripts use configuration files, which you<br />
modify to configure your application’s port usage and to load, configure, and start<br />
the system, library, and user <strong>ACE</strong>s for your application.<br />
The default system initialization startup script (<strong>SDK</strong>installpath/bin/armbe/ixstart)<br />
loads the <strong>IXA</strong> <strong>SDK</strong> components and drivers and sets up the necessary<br />
Linux * device entries. It then runs the configuration utility ixconfig. This utility<br />
reads the system configuration file, <strong>SDK</strong>installpath/bin/arm-be/ixsys.config.<br />
l<br />
l<br />
You must modify the system configuration file to configure the ports and interface<br />
<strong>ACE</strong>s. The script starts the interface <strong>ACE</strong>s. See “Using Startup Scripts and Configuration<br />
Files” on page 36.<br />
You must specify any micro<strong>ACE</strong>s you want to start in the system configuration<br />
file, and specify where to find the compiled microcode images for your application.<br />
The script starts the microengines and the micro<strong>ACE</strong>s.<br />
Revision 3.3, August 2001<br />
Configuring and Starting <strong>IXA</strong> Systems 35
Using Startup Scripts and Configuration Files<br />
l<br />
l<br />
You can modify the system configuration file to run other startup scripts, such as<br />
those supplied for the library <strong>ACE</strong>s. See “Setting Up Particular Configurations”<br />
on page 39.<br />
You can modify the system configuration file to start user <strong>ACE</strong>s, either directly<br />
(using the ace keyword) or by running the ixsh utility. See “Launching Application<br />
<strong>ACE</strong>s” on page 46.<br />
For Additional<br />
Information<br />
l<br />
l<br />
l<br />
For information on the system and library <strong>ACE</strong>s, see Chapter 7, “Interface<br />
<strong>ACE</strong>s,” and Chapter 8, “Stack and Library <strong>ACE</strong>s.”<br />
For detailed reference information on the keywords and syntax <strong>of</strong> the configuration<br />
files, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Configuration files for sample applications that use various combinations <strong>of</strong><br />
library <strong>ACE</strong>s can be found in the following location:<br />
<strong>SDK</strong>installpath/src/microace/apps<br />
Using Startup Scripts and Configuration Files<br />
The <strong>IXA</strong> <strong>SDK</strong> provides sample scripts and configuration files that start and configure<br />
the interface <strong>ACE</strong>s and other library <strong>ACE</strong>s in typical configurations. These files are<br />
fully commented. To start a particular configuration <strong>of</strong> ports and <strong>ACE</strong>s, including<br />
interface <strong>ACE</strong>s and some set <strong>of</strong> library and user <strong>ACE</strong>s, you use the supplied startup<br />
scripts, modifying their configuration files for your application and configuration.<br />
The basic procedure for starting and exiting the <strong>IXA</strong> system is as follows:<br />
1. Determine the addresses for your network topology, and modify the system<br />
configuration file, ixsys.config, to set up the port configuration<br />
2. Create the necessary configuration files for the library <strong>ACE</strong>s you are using:<br />
— For the L2 bridging <strong>ACE</strong>, modify l2bridge.config.<br />
— For the L3 forwarder <strong>ACE</strong>, modify l3forwarder.config.<br />
— For the NAT <strong>ACE</strong>, modify nat.config.<br />
3. Add sh commands to the system configuration file, ixsys.config, to run the<br />
startup script for each included library <strong>ACE</strong>, specifying the <strong>ACE</strong> name and<br />
configuration file you have created for each one.<br />
4. After booting the IXDP1200 Advanced Development Platform, run the startup<br />
script in the command shell:<br />
$ ./ixstart<br />
5. To shut down the modules, run the termination script in the command shell:<br />
$ ./ixstop<br />
36 Configuring and Starting <strong>IXA</strong> Systems<br />
Revision 3.3, August 2001
The System Configuration File<br />
Starting and<br />
Initializing<br />
Interface <strong>ACE</strong>s<br />
When you invoke startup script at system boot it does the following:<br />
l<br />
l<br />
l<br />
l<br />
Activates the specified ports.<br />
Sets up and starts the input and output interface <strong>ACE</strong>s according to the specified<br />
configuration.<br />
Configures and enables the microengines using Resource Manager calls.<br />
Starts threads on the microengines for each port.<br />
Microengine<br />
Threads<br />
The configuration script associates each port to be used with one <strong>of</strong> the six IXP1200<br />
microengines. The script starts the appropriate threads on each microengine,<br />
according to the ports associated with it, so that enough threads are available for each<br />
port.<br />
l<br />
l<br />
l<br />
Each microengine has four threads.<br />
One gigabit port requires eight threads, so it takes two 2 input microblock groups<br />
to handle it.<br />
One 10/100BaseT port requires one thread, so a microengine can handle up to<br />
four such ports.<br />
For example, an 8/1 configuration could use two microengines for input on the<br />
gigabit port, and two for input on the 8 10/100BaseT ports. This leaves two microengines<br />
to handle output for all ports.<br />
The System Configuration File<br />
The system configuration file specifies the following information for use by the<br />
startup script:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Which ports to use, and their IP address information.<br />
The microcode image to be loaded on each microengine.<br />
The configuration for the input and output interface <strong>ACE</strong>s.<br />
Other micro<strong>ACE</strong>s to be started, including stack and library <strong>ACE</strong>s your application<br />
will use.<br />
Bind configurations for micro<strong>ACE</strong>s (both static and dynamic)<br />
Shell commands to run. Run the ixsh utility to create, run, and bind conventional<br />
<strong>ACE</strong>s, and run other configuration scripts.<br />
The following annotated system configuration file shows how to start and configure<br />
the network interfaces and <strong>ACE</strong>s. This example loads the L3 forwarder library <strong>ACE</strong>,<br />
stack <strong>ACE</strong>, and input and output <strong>ACE</strong>s. It sets up binding such that the forwarder<br />
receives packets directly from the input <strong>ACE</strong> and sends them directly to the stack<br />
<strong>ACE</strong> and the output <strong>ACE</strong>.<br />
Revision 3.3, August 2001<br />
Configuring and Starting <strong>IXA</strong> Systems 37
The System Configuration File<br />
Configuring<br />
Network<br />
Interfaces<br />
# ixsys.config<br />
# *********************************************************<br />
# Setup file for the ixconfig application that configures the<br />
# L3Fwdr library <strong>ACE</strong>, stack <strong>ACE</strong>, and interface <strong>ACE</strong>s<br />
# Specifies:<br />
# - Network interfaces to be started at system boot<br />
# - Micro<strong>ACE</strong>s to be started at system boot (interface, L3Fwdr)<br />
# - Conventional <strong>ACE</strong>s to be started at system boot (stackAce)<br />
# - Bind configuration<br />
# - Shell commands to be run<br />
# *********************************************************<br />
#<br />
# Specify interfaces<br />
interface 0 10.1.0.1 10.1.0.255 255.255.255.0 00:01:02:03:04:05 0<br />
interface 1 10.2.0.1 10.2.0.255 255.255.255.0 00:01:02:03:04:06 0<br />
interface 2 10.3.0.1 10.3.0.255 255.255.255.0 00:01:02:03:04:07 0<br />
interface 3 10.4.0.1 10.4.0.255 255.255.255.0 00:01:02:03:04:08 0<br />
interface 4 10.5.0.1 10.5.0.255 255.255.255.0 00:01:02:03:04:09 0<br />
interface 5 10.6.0.1 10.6.0.255 255.255.255.0 00:01:02:03:04:10 0<br />
interface 6 10.7.0.1 10.7.0.255 255.255.255.0 00:01:02:03:04:11 0<br />
interface 7 10.8.0.1 10.8.0.255 255.255.255.0 00:01:02:03:04:12 0<br />
interface 16 10.17.0.1 10.17.0.255 255.255.255.0 00:01:02:03:04:21 0<br />
NOTE:<br />
These lines tell the ixconfig script to run nine network interfaces. The first<br />
eight (0-7) are 10/100BaseT Ethernet ports, the last (16) is a gigabit Ethernet<br />
port. The ixconfig script uses this information to pass the appropriate<br />
configuration parameters when it creates the input and output micro<strong>ACE</strong>s.<br />
Identifying<br />
Microcode<br />
Images<br />
# **********************************************************<br />
# Specify the microcode image (.u<strong>of</strong>) files<br />
file 0 ./SlowIngressL3.u<strong>of</strong><br />
file 1 ./SlowEgressRR.u<strong>of</strong><br />
file 2 ./FastIngressL3-seq1.u<strong>of</strong><br />
file 3 ./FastIngressL3-seq2.u<strong>of</strong><br />
file 4 ./FastEgressFifo.u<strong>of</strong><br />
NOTE:<br />
These lines tell the ixconfig script which microcode image files to load.<br />
Each microcode image combines the microblocks for the input <strong>ACE</strong> and the<br />
L3Fwdr <strong>ACE</strong> with a dispatch loop.<br />
The <strong>IXA</strong> <strong>SDK</strong> also provides microcode image files that combine input, L2<br />
bridging, L3 forwarding, and NAT. The ixconfig script uses the Resource<br />
Manager library to load the code to the microengines.<br />
Starting and<br />
Configuring<br />
Aces<br />
# **************************************************************<br />
# Specify the micro<strong>ACE</strong>s<br />
microace ifaceInput ./ingressAce none 0 1<br />
microace ifaceOutput ./egressAce none 1 2<br />
microace L3Fwdr ./l3_forward_ace none 0 3 ifaceInput<br />
38 Configuring and Starting <strong>IXA</strong> Systems<br />
Revision 3.3, August 2001
Setting Up Particular Configurations<br />
NOTE:<br />
These lines tell the ixconfig script to launch three micro<strong>ACE</strong>s: the input,<br />
output, and L3Fwdr <strong>ACE</strong>s. The script uses the specified <strong>ACE</strong> single object<br />
file names to launch the core components <strong>of</strong> the micro<strong>ACE</strong>s. For example,<br />
l3_forward_ace is the <strong>ACE</strong> single object file name for the core component<br />
<strong>of</strong> the L3fwdr <strong>ACE</strong>. The ixconfig script uses OMS calls to create the new<br />
<strong>ACE</strong>s.<br />
# *************************************************************<br />
# Specify the conventional <strong>ACE</strong>s (such as stack <strong>ACE</strong>s)<br />
ace stackAce ./kstack none 3 ifaceInput<br />
NOTE:<br />
This line tells the ixconfig script to launch the stack <strong>ACE</strong>, using the<br />
specified <strong>ACE</strong> single object file name, kstack. The ixconfig script uses<br />
OMS calls to create the new <strong>ACE</strong>.<br />
# **************************************************************<br />
# Specify the bindings<br />
bind static ifaceInput/default L3Fwdr<br />
bind static L3Fwdr/out_if ifaceOutput<br />
bind regular L3Fwdr/out_if ifaceOutput<br />
bind regular L3Fwdr/stack stackAce<br />
bind regular stackAce/tx ifaceOutput<br />
NOTE:<br />
These lines tell the ixconfig script to bind the three micro<strong>ACE</strong>s statically as<br />
specified in the dispatch loop. They also creates dynamic bindings from the<br />
forwarder to the output <strong>ACE</strong> and stack <strong>ACE</strong>, and from the stack <strong>ACE</strong> to the<br />
output <strong>ACE</strong>. The ixconfig script uses OMS calls to create the bindings.<br />
# *************************************************************<br />
# Run the startup scripts for the stack <strong>ACE</strong><br />
# and L3 forwarding <strong>ACE</strong>.<br />
sh ./stackconfig ./ixsys.config<br />
sh ./l3config L3Fwdr ./ixsys.config ./route.config-sys-l3fwdr<br />
NOTE:<br />
These lines tell the ixconfig script to run the stackconfig utility to<br />
configure the stack <strong>ACE</strong> with the interface information, and to run the<br />
l3config utility to set up a simple route table. These utilities are in the same<br />
directory as ixsys.config. The l3config utility uses the forwarder’s configuration<br />
crosscalls to add a basic set <strong>of</strong> routes, as specified in the file<br />
route.config-sys-l3fwdr.<br />
Setting Up Particular Configurations<br />
This section shows how to set up the configuration files when using the library <strong>ACE</strong>s<br />
for specific tasks. It shows the following examples:<br />
l “Configuring an L2 Bridge” on page 40<br />
Revision 3.3, August 2001<br />
Configuring and Starting <strong>IXA</strong> Systems 39
Setting Up Particular Configurations<br />
l “Configuring an L3 Forwarder” on page 42<br />
l “Configuring an L3 Forwarder with NAT” on page 44<br />
NOTE:<br />
In these examples, all the commands are executed from a single directory<br />
containing all the executables and script files. If your files are in different<br />
locations, you must specify the paths relative to the execution directory.<br />
Configuring an<br />
L2 Bridge<br />
This example shows how to configure the IXDP1200 Advanced Development Platform<br />
to act as a layer 2 bridge for the fast Ethernet and gigabit Ethernet ports.<br />
System Configuration File<br />
The system configuration file sets up eight octal ports (ports 0-7) and 1 gigabit port<br />
(port 16).<br />
l<br />
l<br />
On LAN segments connected to ports 0 and 1, there are two fixed nodes that will<br />
not move to a new LAN segment, with MAC addresses 00:aa:bb:cc:dd:00 and<br />
00:aa:bb:cc:dd:01 respectively.<br />
On the segments connected to other ports, the MAC addresses <strong>of</strong> connected nodes<br />
are not known at startup.<br />
IXP1200 Evaluation Platform (L2 Bridge)<br />
0 1 2 3 4 5 6 7 16<br />
10.1.0.0/16<br />
10.4.0.0/16<br />
10.2.0.0/16<br />
10.6.0.0/16<br />
10.3.0.0/16<br />
10.7.0.0/16<br />
10.4.0.0/16<br />
10.8.0.0/16<br />
10.17.0.0/16<br />
This configuration file also starts and binds the L2 bridging library <strong>ACE</strong>, and tells the<br />
system startup script to run the L2 bridging configuration script.<br />
# ixsys.config<br />
# Configure ports<br />
interface 0 11.2.10.51 11.2.10.255 255.255.255.0 08:02:03:04:05:06 1<br />
interface 1 11.2.10.52 11.2.10.255 255.255.255.0 08:02:03:04:05:07 1<br />
interface 2 11.2.10.53 11.2.10.255 255.255.255.0 08:02:03:04:05:08 1<br />
interface 3 11.2.10.54 11.2.10.255 255.255.255.0 08:02:03:04:05:09 1<br />
interface 4 11.2.10.55 11.2.10.255 255.255.255.0 08:02:03:04:05:0A 1<br />
interface 5 11.2.10.56 11.2.10.255 255.255.255.0 08:02:03:04:05:0B 1<br />
interface 6 11.2.10.57 11.2.10.255 255.255.255.0 08:02:03:04:05:0C 1<br />
interface 7 11.2.10.58 11.2.10.255 255.255.255.0 08:02:03:04:05:0D 1<br />
interface 16 11.2.10.67 11.2.10.255 255.255.255.0 08:02:03:04:05:16<br />
1<br />
# This line is optional<br />
mode 0<br />
40 Configuring and Starting <strong>IXA</strong> Systems<br />
Revision 3.3, August 2001
Setting Up Particular Configurations<br />
# Specify the microcode image files<br />
file 0 ./SlowIngressL2L3NAT.u<strong>of</strong><br />
file 1 ./SlowEgressRR.u<strong>of</strong><br />
file 2 ./FastIngressL2L3NAT-seq1.u<strong>of</strong><br />
file 3 ./FastIngressL2L3NAT-seq2.u<strong>of</strong><br />
file 4 ./FastEgressFifo.u<strong>of</strong><br />
# Specify the micro<strong>ACE</strong>s<br />
microace ifaceInput ./ingressAce none 0 1<br />
microace ifaceOutput ./egressAce none 1 2<br />
microace L2Bridge ./l2bridge_ace none 0 4<br />
# Specify the bindings<br />
bind static ifaceInput/default L2Bridge<br />
bind static L2Bridge/out_if ifaceOutput<br />
bind regular L2Bridge/out_if ifaceOutput<br />
# Specify the shell command to run the L2 bridge startup script.<br />
sh ./l2config L2Bridge ixsys.config l2bridge.config<br />
L2 Bridging Configuration File<br />
The L2 bridging configuration file adds static forwarding entries to the routing table<br />
and sets up the corresponding port configuration for the L2 bridging <strong>ACE</strong>.<br />
# l2bridge.config<br />
# add forwarding entries<br />
add_fwd_static_entry 0 00:aa:bb:cc:dd:00<br />
add_fwd_static_entry 1 00:aa:bb:cc:dd:01<br />
# set port configuration<br />
set_port_state 0 5<br />
set_port_state 1 5<br />
set_port_state 2 5<br />
set_port_state 3 5<br />
set_port_state 4 5<br />
set_port_state 5 5<br />
set_port_state 6 5<br />
set_port_state 7 5<br />
set_port_state 16 5<br />
enable_port_bridging 0<br />
enable_port_bridging 1<br />
enable_port_bridging 2<br />
enable_port_bridging 3<br />
enable_port_bridging 4<br />
enable_port_bridging 5<br />
enable_port_bridging 6<br />
enable_port_bridging 7<br />
enable_port_bridging 16<br />
set_port_mtu 0 1518<br />
set_port_mtu 1 1518<br />
set_port_mtu 2 1518<br />
Configuring and Starting <strong>IXA</strong> Systems 41<br />
Revision 3.3, August 2001
Setting Up Particular Configurations<br />
set_port_mtu 3 1518<br />
set_port_mtu 4 1518<br />
set_port_mtu 5 1518<br />
set_port_mtu 6 1518<br />
set_port_mtu 7 1518<br />
set_port_mtu 16 1518<br />
Configuring an<br />
L3 Forwarder<br />
This example shows how to configure the IXDP1200 Advanced Development Platform<br />
to act as a layer 3 forwarder for an IP network. This simple example sets up<br />
static routes, populating the routing table using the L3 forwarder configuration<br />
script. The application would use the L3 forwarder’s crosscalls to manage the routing<br />
table at run time.<br />
System Configuration File<br />
This example configures eight octal ports (ports 0-7) and 1 gigabit port (port 16).<br />
l Each port is on a different LAN segment and each LAN segment is a different<br />
network, like an enterprise-wide router.<br />
l<br />
The default gateway is 192.10.11.12 and is on network 192.10.11.0, connected to<br />
port 1.<br />
IXP1200 Evaluation Platform (L3 Forwarder)<br />
0 1 2 3 4 5 6 7 16<br />
10.1.0.0/16<br />
192.10.11.0/24<br />
(Gateway)<br />
10.1.128/24<br />
10.1.192/24<br />
10.1.224/24<br />
10.3.0.0/24<br />
10.4.0.0/24<br />
Router<br />
10.5.0.0/24<br />
10.6.0.0/24<br />
10.7.0.0/24<br />
10.8.0.0/24<br />
10.17.0.0/24<br />
This configuration file also starts and binds the L3 forwarder library <strong>ACE</strong>, and tells<br />
the system startup script to run the L3 forwarder configuration script.<br />
# ixsys.config<br />
# Configure ports<br />
interface 0 10.1.0.1 10.1.0.255 255.255.255.0 00:01:02:03:04:05 0<br />
interface 1 192.10.11.1 192.10.11.255 255.255.255.0<br />
00:01:02:03:04:06 0<br />
interface 2 10.3.0.1 10.3.0.255 255.255.255.0 00:01:02:03:04:07 0<br />
interface 3 10.4.0.1 10.4.0.255 255.255.255.0 00:01:02:03:04:08 0<br />
interface 4 10.5.0.1 10.5.0.255 255.255.255.0 00:01:02:03:04:09 0<br />
interface 5 10.6.0.1 10.6.0.255 255.255.255.0 00:01:02:03:04:10 0<br />
interface 6 10.7.0.1 10.7.0.255 255.255.255.0 00:01:02:03:04:11 0<br />
interface 7 10.8.0.1 10.8.0.255 255.255.255.0 00:01:02:03:04:12 0<br />
42 Configuring and Starting <strong>IXA</strong> Systems<br />
Revision 3.3, August 2001
Setting Up Particular Configurations<br />
interface 16 10.17.0.1 10.17.0.255 255.255.255.0 00:01:02:03:04:20 0<br />
# Specify the microcode images<br />
file 0 ./SlowIngressL3.u<strong>of</strong><br />
file 1 ./SlowEgressRR.u<strong>of</strong><br />
file 2 ./FastIngressL3-seq1.u<strong>of</strong><br />
file 3 ./FastIngressL3-seq2.u<strong>of</strong><br />
file 4 ./FastEgressFifo.u<strong>of</strong><br />
# Specify the micro<strong>ACE</strong>s<br />
microace ifaceInput ./ingressAce none 0 1<br />
microace ifaceOutput ./egressAce none 1 2<br />
microace L3Fwdr ./l3_forward_ace none 0 3 ifaceInput<br />
# Specify the conventional <strong>ACE</strong>s - in this case, the stack <strong>ACE</strong><br />
ace stackAce ./kstack none 3 ifaceInput<br />
# Specify the bindings<br />
bind static ifaceInput/default L3Fwdr<br />
bind static L3Fwdr/out_if ifaceOutput<br />
bind regular L3Fwdr/out_if ifaceOutput<br />
bind regular L3Fwdr/stack stackAce<br />
bind regular stackAce/tx ifaceOutput<br />
# Run the startup scripts for stack <strong>ACE</strong> and L3Fwdr<br />
sh ./stackconfig ./ixsys.config<br />
sh ./l3config L3Fwdr ./ixsys.config ./route.config-sys-l3fwdr<br />
#end <strong>of</strong> ixsys.config<br />
L3 Forwarder Configuration File<br />
The L3 forwarder configuration file adds static routes to the forwarding table and sets<br />
up the default route and gateway.<br />
# l3forwarder.config<br />
# route information for the L3 forwarder<br />
routeadd 10.1.0.0 255.255.0.0 0.0.0.0 0<br />
routeadd 192.10.11.0 255.255.255.0 0.0.0.0 1<br />
routeadd 10.3.0.0 255.255.255.0 0.0.0.0 2<br />
routeadd 10.4.0.0 255.255.255.0 0.0.0.0 3<br />
routeadd 10.5.0.0 255.255.255.0 0.0.0.0 4<br />
routeadd 10.6.0.0 255.255.255.0 0.0.0.0 5<br />
routeadd 10.7.0.0 255.255.255.0 0.0.0.0 6<br />
routeadd 10.8.0.0 255.255.255.0 0.0.0.0 7<br />
routeadd 10.17.0.0 255.255.255.0 0.0.0.0 16<br />
#default route and gateway<br />
routeadd 192.10.11.5 255.255.255.0 0.0.0.0 1<br />
routeadd 0.0.0.0 0.0.0.0 192.10.11.5 1<br />
#end <strong>of</strong> configuration.<br />
Configuring and Starting <strong>IXA</strong> Systems 43<br />
Revision 3.3, August 2001
Setting Up Particular Configurations<br />
Configuring an<br />
L3 Forwarder<br />
with NAT<br />
This example shows how to configure the IXDP1200 Advanced Development Platform<br />
to act as a router with NAT functions, as would typically be used on the border<br />
between two or more networks.<br />
The example sets up the same network topology described in “Configuring an L3<br />
Forwarder” on page 42, adding NAT functionality<br />
l<br />
l<br />
The 192.10.11.0 network is the external network—that is, the IP addresses on this<br />
network are globally unique. The other networks are internal to the site.<br />
— The IP address <strong>of</strong> port 1 on the 192.10.11.0 network is 192.10.11.10.<br />
— The site uses the IP addresses from 192.10.11.50 through 192.10.11.60 as global<br />
unique IP addresses to be used by the internal nodes.<br />
The 10.1.0.0 network is subnetted into 10.1.128.0, 10.1.192.0, 10.1.224.0 networks.<br />
This example configures the NAT library <strong>ACE</strong> to enforce the following policies on the<br />
traffic between the external network and 10.1.0.0 network:<br />
l<br />
l<br />
l<br />
l<br />
Translate 10.1.0.10 to 192.10.11.50 and the reverse.<br />
Translate 10.1.0.11 to 192.10.11.51 and the reverse.<br />
Translate 10.1.0.12 to 192.10.11.52 and the reverse.<br />
For hosts from the 10.1.128.0 network, map to 192.10.11.53 address and the<br />
reverse.<br />
l For hosts from the 10.1.192.0 network, dynamically map to addresses 192.10.11.54<br />
through 192.10.11.58.<br />
l<br />
l<br />
For requests coming onto 192.10.11.10, TCP/UDP port 1000, load balance the<br />
requests, alternating between the nodes 10.1.30.5 and 10.1.30.6.<br />
Drop packets that are destined to IP addresses greater than 10.1.30.10 and less<br />
than 10.1.30.40.<br />
l Pass all packets originating from 10.5.0.0.<br />
System Configuration File<br />
This example configures eight octal ports (ports 0-7) and 1 gigabit port (port 16). It<br />
starts and binds the following <strong>ACE</strong>s, in addition to the interface <strong>ACE</strong>s:<br />
l<br />
l<br />
l<br />
l<br />
the L3 forwarder library <strong>ACE</strong><br />
the L2 bridging library <strong>ACE</strong><br />
the NAT library <strong>ACE</strong><br />
the stack <strong>ACE</strong>.<br />
The file then tells the system startup script to run the configuration scripts for all <strong>of</strong><br />
these <strong>ACE</strong>s.<br />
# ixsys.config<br />
# Configure ports<br />
interface 0 10.1.0.1 10.1.0.255 255.255.255.0 00:01:02:03:04:05 0<br />
interface 1 10.2.0.1 10.2.0.255 255.255.255.0 00:01:02:03:04:06 0<br />
44 Configuring and Starting <strong>IXA</strong> Systems<br />
Revision 3.3, August 2001
Setting Up Particular Configurations<br />
interface 2 10.3.0.1 10.3.0.255 255.255.255.0 00:01:02:03:04:07 0<br />
interface 3 10.4.0.1 10.4.0.255 255.255.255.0 00:01:02:03:04:08 0<br />
interface 4 10.5.0.1 10.5.0.255 255.255.255.0 00:01:02:03:04:09 0<br />
interface 5 10.6.0.1 10.6.0.255 255.255.255.0 00:01:02:03:04:10 0<br />
interface 6 10.7.0.1 10.7.0.255 255.255.255.0 00:01:02:03:04:11 0<br />
interface 7 10.8.0.1 10.8.0.255 255.255.255.0 00:01:02:03:04:12 0<br />
interface 15 10.16.0.1 10.16.0.255 255.255.255.0 00:01:02:03:04:20 0<br />
# Specify microcode images<br />
file 0 ./SlowIngressL2L3NAT.u<strong>of</strong><br />
file 1 ./SlowEgressRR.u<strong>of</strong><br />
file 2 ./FastIngressL2L3NAT-seq1.u<strong>of</strong><br />
file 3 ./FastIngressL2L3NAT-seq2.u<strong>of</strong><br />
file 4 ./FastEgressFifo.u<strong>of</strong><br />
# Specify the micro<strong>ACE</strong>s<br />
microace ifaceInput ./ingressAce none 0 1<br />
microace ifaceOutput ./egressAce none 1 2<br />
microace L3Fwdr ./l3_forward_ace none 0 3 ifaceInput<br />
microace nat ./Nat none 0 5 natc 3<br />
# Specify the convention <strong>ACE</strong>s: stack <strong>ACE</strong> and NAT <strong>ACE</strong><br />
ace stackAce ./kstack none 3 ifaceInput<br />
ace natc ./natctlr none 2 nat 1<br />
# Specify bindings<br />
bind static ifaceInput/default nat<br />
bind static L3Fwdr/out_if ifaceOutput<br />
bind static L2Bridge/default nat<br />
bind static nat/PASS<br />
L3Fwdr<br />
bind regular nat/CONFIG<br />
bind regular L3Fwdr/stack<br />
bind regular stackAce/tx<br />
bind regular natc/default<br />
natc<br />
stackAce<br />
ifaceOutput<br />
nat<br />
# Run startup scripts for stack <strong>ACE</strong>, L3Fwdr <strong>ACE</strong>, and NAT <strong>ACE</strong><br />
sh ./stackconfig ./ixsys.config<br />
sh ./l3config L3Fwdr ./ixsys.config ./route.config-sys-l3fwdr<br />
sh ./natconfig natc ./nat_l2l3nat.config<br />
#end <strong>of</strong> ixsys.config<br />
NAT Configuration File<br />
This example sets up the NAT configuration rules described above.<br />
# nat.config<br />
# create filter ACL<br />
acl_create 0 0<br />
# create NAT ACL<br />
Configuring and Starting <strong>IXA</strong> Systems 45<br />
Revision 3.3, August 2001
Launching Application <strong>ACE</strong>s<br />
acl_create 1 1<br />
#filter rules here<br />
filter 0 DROP IPDEST > 10.1.30.10, IPDEST < 10.1.30.40<br />
filter 0 PASS IPSRC = 10.5.*.*<br />
# nat action rules<br />
filter 0 NAT IPSRC > 10.1.0.9 , IPSRC < 10.1.0.13<br />
filter 0 NAT IPSRC = 10.2.*.*<br />
filter 0 NAT IPSRC = 10.3.*.*<br />
filter 0 NAT IPDST = 192.10.11.10 , DSTPORT = 1000<br />
# drop the rest <strong>of</strong> packets<br />
filter 0 DROP IPSRC=*.*.*.*<br />
# nat rules<br />
nat_static 1 IPSRC = 10.1.0.10 with 192.10.11.50<br />
nat_static 1 IPSRC = 10.1.0.11 with 192.10.11.51<br />
nat_static 1 IPSRC = 10.1.0.12 with 192.10.11.52<br />
nat_ip_masquerade 1 IPSRC = 10.1.128.* with 192.10.11.53<br />
nat_dynamic 1 IPSRC = 10.1.192.* with 192.10.11.54 4<br />
nat_virtual_server 1 IPDEST = 192.10.11.10, DESTPORT = 1000 with<br />
10.1.30.510.1.30.6<br />
#end <strong>of</strong> nat.config<br />
Launching Application <strong>ACE</strong>s<br />
During development, you might need to load and start application <strong>ACE</strong>s interactively.<br />
To run and test an application, you must load and run <strong>ACE</strong>s and create the<br />
bindings that control traffic flow. You can do this from the command line, in a script,<br />
or from a manager or launcher program. Similarly, you can stop <strong>ACE</strong>s and change<br />
binding in any <strong>of</strong> these ways.<br />
l<br />
l<br />
To launch and control the application <strong>ACE</strong>s from a script or the command line,<br />
use the ixsh utility provided in $IXROOT/bin/. This utility is described in<br />
Chapter 8, “Command-Line Tools,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
To launch and control an application <strong>ACE</strong> from a manager or launcher program,<br />
do the following:<br />
a. Open a CAP in its own thread, and use it to open a Resolver session.<br />
b. To start an <strong>ACE</strong>, call the function ix_res_create_ace, passing the Linux path<br />
to the <strong>ACE</strong> executable.<br />
c. To bind targets and <strong>ACE</strong>s, call the function ix_res_bind. Use ix_res_unbind<br />
to change the traffic flow.<br />
d. To halt an <strong>ACE</strong>, call the function ix_res_delete_ace.<br />
These functions and procedures are described in Chapter 2, “OMS Global<br />
Services API,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
46 Configuring and Starting <strong>IXA</strong> Systems<br />
Revision 3.3, August 2001
Chapter 5<br />
Controlling Packet Flow<br />
This chapter explains how packets flow into and out <strong>of</strong> an <strong>IXA</strong> application according<br />
to both the physical connections and the logical connections, known as bindings. It<br />
describes the physical network interfaces, the system and default targets to which<br />
you can direct packets, and how to create additional targets.<br />
This chapter contains the following topics:<br />
l “Defining Packet Flow” on page 47<br />
l “Binding Targets as Packet Destinations” on page 48<br />
l “Defining Additional Targets” on page 50<br />
l “Directing Packets to a Target” on page 51<br />
l “Using Targets for Packet Processing” on page 51<br />
l “Receiving and Transmitting on Network Interface Ports” on page 53<br />
Defining Packet Flow<br />
Physically, packets flow into an IXP1200 system through network interfaces (ports),<br />
and back out through the same or other ports. Logically, packets move through an<br />
<strong>IXA</strong> application from one <strong>ACE</strong> to another. <strong>ACE</strong>s are the s<strong>of</strong>tware entities that receive<br />
and dispose <strong>of</strong> packets.<br />
The system defines <strong>ACE</strong>s that communicate directly with the ports. These interface<br />
<strong>ACE</strong>s get packets from ports and send them to application <strong>ACE</strong>s, and receive packets<br />
from application <strong>ACE</strong>s to send out over ports. The application <strong>ACE</strong>s act on the<br />
packets while they are in the IXP1200 system.<br />
Typically several <strong>ACE</strong>s act on packets, at least to transport them to and from the<br />
ports. You determine the path that packets take through your application’s <strong>ACE</strong>s by<br />
binding the <strong>ACE</strong>s together in the order in which packets should encounter them.<br />
Revision 3.3, August 2001<br />
Controlling Packet Flow 47
Binding Targets as Packet Destinations<br />
Physical<br />
Packet Flow<br />
Each IXP1200 system has several physical network interfaces or ports. Depending on<br />
the board configuration, these can be connected directly to the network or to other<br />
packet sources and destinations, such as other IXP1200 boards. The quantity and type<br />
<strong>of</strong> ports also depends on the board configuration. For example, the IXDP1200<br />
Advanced Development Platform has sixteen fast Ethernet (10/100BaseT) ports and<br />
two gigabit Ethernet ports.<br />
Logical Packet<br />
Flow<br />
The <strong>ACE</strong> model <strong>of</strong> packet handling requires that packets be passed among <strong>ACE</strong>s in<br />
an <strong>IXA</strong> application. Therefore, each physical interface is represented in s<strong>of</strong>tware by a<br />
special-purpose system <strong>ACE</strong> called an interface <strong>ACE</strong>. (These are described in more<br />
detail in a later section, “Receiving and Transmitting on Network Interface Ports” on<br />
page 53.)<br />
The <strong>IXA</strong> <strong>SDK</strong> includes system-defined <strong>ACE</strong>s for each <strong>of</strong> the network interfaces in the<br />
IXDP1200 Advanced Development Platform, and for the Linux * TCP/IP stack. The<br />
quantity, types, and names <strong>of</strong> system <strong>ACE</strong>s depend on the physical configuration <strong>of</strong><br />
the IXP1200 system. Your customized system startup script loads and starts system<br />
<strong>ACE</strong>s for each <strong>of</strong> the ports your application uses.<br />
The interface <strong>ACE</strong>s act as s<strong>of</strong>tware packet sources and destinations for the application.<br />
Packets flow through an IXP1200 system from a port through an interface <strong>ACE</strong><br />
to one or more application <strong>ACE</strong>s, and out through an interface <strong>ACE</strong> to a port, as<br />
shown in the following figure:<br />
Input interface <strong>ACE</strong> Applications and modules Output interface <strong>ACE</strong><br />
Packet flow<br />
match: act on<br />
?<br />
not<br />
match<br />
?<br />
not<br />
Drop<br />
The connections between <strong>ACE</strong>s that determine how packets flow are called bindings.<br />
The API provides the tools for you to bind <strong>ACE</strong>s together. Packets flow through an<br />
IXP1200 system only after you have created bindings.<br />
Binding Targets as Packet Destinations<br />
In an <strong>ACE</strong>, packets flow in only one direction: through the <strong>ACE</strong> to a target within the<br />
<strong>ACE</strong>. A target provides a way to connect an <strong>ACE</strong> to a destination for packets. Each<br />
<strong>ACE</strong> can have multiple targets.<br />
The manager program for the application, which creates the <strong>ACE</strong>s, can also determine<br />
the packet flow by binding targets to other <strong>ACE</strong>s.<br />
l<br />
For a packet to flow into an <strong>ACE</strong>, the application must bind the target in the<br />
packet’s source <strong>ACE</strong> to that <strong>ACE</strong>.<br />
48 Controlling Packet Flow<br />
Revision 3.3, August 2001
Binding Targets as Packet Destinations<br />
l<br />
For a packet to flow out <strong>of</strong> an <strong>ACE</strong>, the application must:<br />
a. Create a target as part <strong>of</strong> the <strong>ACE</strong> (in the <strong>ACE</strong> initialization code).<br />
b. Bind the target to a destination <strong>ACE</strong>, using the function ix_res_bind in the<br />
manager program that creates the <strong>ACE</strong>, or using a command-line utility.<br />
c. Direct the packet to the target in an action function in the <strong>ACE</strong> action code.<br />
This means that every source that sends packets must be represented by an <strong>ACE</strong> that<br />
contains a target, and every destination must be represented by an <strong>ACE</strong>. A packet<br />
source or destination can be, for example, another <strong>ACE</strong> in the same application, an<br />
<strong>ACE</strong> in a different application, or a network interface or protocol stack, represented<br />
by a system <strong>ACE</strong>.<br />
<strong>ACE</strong> A<br />
Packet flow<br />
rule match: action<br />
no match: action<br />
Target 1<br />
Output interface <strong>ACE</strong><br />
Target 2<br />
Targets bound to interface <strong>ACE</strong><br />
Target bound to <strong>ACE</strong> B<br />
<strong>ACE</strong> B<br />
action<br />
Target 3<br />
Binding<br />
Targets and<br />
<strong>ACE</strong>s<br />
Targets are represented in your action code by ix_target structures. Each <strong>ACE</strong> is<br />
automatically initialized with the default target object named default. You can<br />
create additional targets; see “Defining Additional Targets” on page 50.<br />
All targets, including the predefined targets, are initially unbound. You must bind an<br />
<strong>ACE</strong>’s targets before packets can flow. In a simple application, you bind the default<br />
target to the next <strong>ACE</strong> in the normal flow <strong>of</strong> traffic.<br />
You bind application <strong>ACE</strong>s to system <strong>ACE</strong>s to provide packet sources and destinations<br />
for your application. For example, to pass packets out to the network, bind the<br />
system-defined default target <strong>of</strong> MyAce to the output interface <strong>ACE</strong>, as follows:<br />
ix_res_bind (res_session, "/MyAce/default", "/ifaceOutput");<br />
To receive packets from the network, bind the target <strong>of</strong> the input interface <strong>ACE</strong>. For<br />
example:<br />
ix_res_bind (res_session, "/ifaceInput/default", "/MyAce");<br />
NOTE:<br />
For details on the naming <strong>of</strong> <strong>ACE</strong>s, targets, and system <strong>ACE</strong>s, see the <strong>IXA</strong><br />
<strong>SDK</strong> Reference.<br />
In addition to the API function ix_res_bind, the <strong>IXA</strong> <strong>SDK</strong> provides utilities for<br />
binding that you can use from the command line or from a script.<br />
l<br />
The ixbind command binds a target to an <strong>ACE</strong> directly.<br />
Controlling Packet Flow 49<br />
Revision 3.3, August 2001
Defining Additional Targets<br />
l<br />
The ixsh utility has a bind command that you can use as part <strong>of</strong> a series <strong>of</strong> <strong>ACE</strong><br />
management commands.<br />
Typically, the startup script and configuration file determine the bindings for an<br />
application at startup. For details on these and other commands and utilities, see the<br />
<strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Unbound<br />
Targets<br />
Some applications, such as monitors and most intrusion detection systems, do not<br />
forward packets. An <strong>ACE</strong> performing such a task simply discards the packets.<br />
Directing a packet to a target without binding the target to a destination <strong>ACE</strong> causes<br />
packets to be dropped, as shown in the following figure.<br />
<strong>ACE</strong> A<br />
Packet flow<br />
rule match: action<br />
no match: action<br />
Target 1<br />
Output interface <strong>ACE</strong><br />
Target 2<br />
Targets bound to destinations<br />
<strong>ACE</strong> B<br />
rule match: action<br />
no match: action<br />
Target 3<br />
Target 4<br />
Unbound target<br />
Dropped<br />
If you leave a target unbound, then direct packets to it, those packets are dropped.<br />
However, you can drop packets more efficiently by not directing them to a target at<br />
all, while still returning RULE_DONE from the final action function. See “Directing<br />
Packets to a Target” on page 51.<br />
Defining Additional Targets<br />
The set <strong>of</strong> targets in an <strong>ACE</strong> represents the set <strong>of</strong> all possible packet destinations in<br />
that <strong>ACE</strong>, across all actions.<br />
l<br />
l<br />
In a simple case, an <strong>ACE</strong> passes most packets to the default target bound to an<br />
egress interface or to the next processing <strong>ACE</strong>, and defines another target to pass<br />
exception-case packets to a control-module <strong>ACE</strong> for exception processing.<br />
An <strong>ACE</strong> that performs a demultiplexing function, for example, might have<br />
multiple outgoing targets for different types <strong>of</strong> packets.<br />
To create additional targets within your application <strong>ACE</strong>s, you must do the<br />
following:<br />
1. In the ix_init function that creates the <strong>ACE</strong>, allocate an ix_target structure.<br />
2. Create the target using the ix_target_init function.<br />
ix_error ix_init (int argc, char **argv, ix_ace **acep)<br />
{<br />
50 Controlling Packet Flow<br />
Revision 3.3, August 2001
Directing Packets to a Target<br />
//allocate ace and target, pass to init fns<br />
ix_ace myace;<br />
ix_target mytarget;<br />
}<br />
ix_ace_init (myace, argv[1]);//<strong>ACE</strong> name passed in<br />
ix_target_init (mytarget, myace, "MyTarget");<br />
...<br />
Directing Packets to a Target<br />
Action functions in the <strong>ACE</strong> determine the path that a packet takes through an application<br />
by specifying whether the packet has completed processing and by directing<br />
the packet to a specific target.<br />
Packets are represented within action code by an ix_buffer object.<br />
An action function must:<br />
1. Use the function ix_target_take to direct the current packet buffer to the specified<br />
target, if processing is done.<br />
2. Return one <strong>of</strong> the following constant values to indicate whether rule processing<br />
should continue on this packet buffer:<br />
— RULE_DONE<br />
— RULE_CONT<br />
If all action functions specified by successful rules are executed and none <strong>of</strong> them<br />
returns RULE_DONE to indicate that it has disposed <strong>of</strong> the packet buffer, the buffer is<br />
passed to the <strong>ACE</strong>’s default target.<br />
For more information on writing action functions, see the following:<br />
l<br />
l<br />
Chapter 10, “Initializing and Acting on Packets in an <strong>ACE</strong>.”<br />
Chapter 3, “The ASL Core Primary Package API,” in the <strong>IXA</strong> <strong>SDK</strong> Reference<br />
Using Targets for Packet Processing<br />
An application can bind targets to several <strong>ACE</strong>s, possibly on different processors, in<br />
order to perform serial processing on packets, or to distribute packets to different<br />
routes.<br />
Serial Packet<br />
Flow<br />
The following figure illustrates a simple cascade <strong>of</strong> <strong>ACE</strong>s defined by their target<br />
bindings.<br />
Controlling Packet Flow 51<br />
Revision 3.3, August 2001
Using Targets for Packet Processing<br />
Input interface <strong>ACE</strong><br />
Target T1<br />
Bound target-to-<strong>ACE</strong><br />
flow<br />
Output interface <strong>ACE</strong><br />
Packet-to-target<br />
flow<br />
Forwarder <strong>ACE</strong><br />
In cache?<br />
Yes: forward<br />
No<br />
Target T3<br />
Target T2<br />
FwdControl <strong>ACE</strong><br />
Update data;<br />
forward<br />
Target T4<br />
In this example:<br />
l<br />
Target T1 is in the system <strong>ACE</strong> that represents an input network interface. T1 is<br />
bound to the Forwarder <strong>ACE</strong>. This directs all incoming traffic to the Forwarder<br />
<strong>ACE</strong>, which handles basic fast-path processing.<br />
l The Forwarder <strong>ACE</strong> contains two targets, T2 and T3. Most traffic is directed to T2,<br />
which is bound to the system <strong>ACE</strong> for the output network interface. Exception<br />
cases are directed to target T3, which is bound to another <strong>ACE</strong>, called FwdControl.<br />
l<br />
The FwdControl <strong>ACE</strong> processes the exception-case packets that it receives from<br />
the Forwarder <strong>ACE</strong>, then directs them to its own target, T4. T4 is also bound to<br />
the system <strong>ACE</strong> for the output network interface, so the exception-case packets<br />
are inserted back into the traffic flow.<br />
Packet Flow<br />
Redirection<br />
Because packets are passed to targets, rather than directly to other <strong>ACE</strong>s, you can<br />
easily insert another operation into your application by adding another <strong>ACE</strong> and<br />
rebinding the targets.<br />
For example, you could add a Firewall <strong>ACE</strong> to decide whether or not to allow<br />
packets through the output interface. The following figure illustrates how you can<br />
insert this <strong>ACE</strong> without having to change the logic or code <strong>of</strong> the existing <strong>ACE</strong>s,<br />
simply by rebinding the targets T2 (in Forwarder) and T4 (in FwdControl) to the<br />
Firewall <strong>ACE</strong>.<br />
52 Controlling Packet Flow<br />
Revision 3.3, August 2001
Receiving and Transmitting on Network Interface Ports<br />
Network interface <strong>ACE</strong><br />
Network interface <strong>ACE</strong><br />
Target T1<br />
Firewall <strong>ACE</strong><br />
Yes<br />
No<br />
Packet OK?<br />
Target T5<br />
Target T6<br />
Drop<br />
Packet-to-target<br />
flow<br />
Forwarder <strong>ACE</strong><br />
In cache?<br />
Yes: forward<br />
No<br />
Target T3<br />
Target T2<br />
Bound target-to-<strong>ACE</strong><br />
flow<br />
FwdControl <strong>ACE</strong><br />
Update data;<br />
forward<br />
Target T4<br />
In the example, the Firewall <strong>ACE</strong>’s target T5 is bound to the output network interface,<br />
allowing packets into traffic, and target T6 is unbound, allowing packets to be<br />
discarded.<br />
Receiving and Transmitting on Network Interface Ports<br />
In the s<strong>of</strong>tware, physical network interface ports are represented by a specialpurpose<br />
entity called an interface <strong>ACE</strong>. Interface <strong>ACE</strong>s are created and initialized at<br />
system startup, using a configuration script that you customize. You configure the<br />
startup scripts to load and start an input <strong>ACE</strong> and an output <strong>ACE</strong>, configuring them<br />
to receive and transmit on the ports you need, depending on both the physical configuration<br />
<strong>of</strong> the IXP1200 system and on how you plan to use it. For the IXDP1200<br />
Advanced Development Platform, the <strong>IXA</strong> <strong>SDK</strong> provides two types <strong>of</strong> ports, the fast<br />
Ethernet (10/100) ports and the gigabit Ethernet ports. The interface <strong>ACE</strong>s can<br />
handle both types <strong>of</strong> port.<br />
An interface <strong>ACE</strong> is a type <strong>of</strong> system <strong>ACE</strong>. A system <strong>ACE</strong>, unlike other <strong>ACE</strong>s, does<br />
not classify packets, but only transmits them. (The other type <strong>of</strong> system <strong>ACE</strong>, the stack<br />
<strong>ACE</strong>, represents a protocol stack.) However, it looks like an <strong>ACE</strong> to the OMS Name<br />
Server, which allows you to direct packets to and from the ports.<br />
System <strong>ACE</strong>s are implemented as micro<strong>ACE</strong>s—that is, they run partly on the<br />
IXP1200’s microengines, and partly on the core processor.<br />
l<br />
l<br />
The microengine pieces are called microblocks. The microblocks communicate<br />
directly with the hardware ports, assembling mpackets into packet buffers and<br />
disassembling them for transmission.<br />
The core component communicates with the microblocks, and with other <strong>ACE</strong>s.<br />
The input <strong>ACE</strong> exports a crosscall interface that other parts <strong>of</strong> your application<br />
can use to configure it. The output <strong>ACE</strong> does not require further configuration<br />
after installation.<br />
Revision 3.3, August 2001<br />
Controlling Packet Flow 53
Receiving and Transmitting on Network Interface Ports<br />
The input interface <strong>ACE</strong>, like all <strong>ACE</strong>s, has a default target. You must bind the default<br />
target to the micro<strong>ACE</strong> containing the next microblock in the group. This is a static<br />
binding; that is, you cannot change it at run time. It reflects the processing pipeline<br />
on the microengine, which is part <strong>of</strong> compiled code and cannot change at run time.<br />
You can create a static binding in either <strong>of</strong> the following ways:<br />
l<br />
l<br />
Programmatically, use the Resource Manager function RmBindMicroAce, rather<br />
than the Resolver function ix_res_bind.<br />
In the configuration file for the startup script, use the static flag for the bind utility.<br />
For example:<br />
bind static ifaceInput/default CountMicroAce2<br />
See Also<br />
l Chapter 6, “Writing Micro<strong>ACE</strong>s” on page 55<br />
l Chapter 8, “Stack and Library <strong>ACE</strong>s” on page 87<br />
l The <strong>IXA</strong> <strong>SDK</strong> Reference<br />
54 Controlling Packet Flow<br />
Revision 3.3, August 2001
Chapter 6<br />
Writing Micro<strong>ACE</strong>s<br />
This chapter provides information on the architecture and design <strong>of</strong> micro<strong>ACE</strong>s,<br />
which make use <strong>of</strong> the <strong>Intel</strong> ® IXP1200’s microengines for fast-path processing. It<br />
contains the following topics:<br />
l “Overview” on page 55<br />
l “Micro<strong>ACE</strong> Architectural Elements” on page 56<br />
l “Loading Micro<strong>ACE</strong>s” on page 58<br />
l “Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong>” on page 61<br />
l “Configuring Micro<strong>ACE</strong>s with Crosscalls” on page 68<br />
l “Microblock Types and Groups” on page 68<br />
l “Writing a Dispatch Loop” on page 71<br />
l “Writing a Microblock” on page 75<br />
l “Micro<strong>ACE</strong> Design Example” on page 77<br />
Overview<br />
The micro<strong>ACE</strong> programming model allows a packet-processing application to make<br />
use <strong>of</strong> the IXP1200’s microengines for acceleration <strong>of</strong> fast-path processing.<br />
Micro<strong>ACE</strong>s perform specific tasks such as IP forwarding, network address translation<br />
(NAT), and IP filtering.<br />
A micro<strong>ACE</strong> has two logical components, running on different processors:<br />
l<br />
A microblock contains fast-path packet processing logic which you write in microcode<br />
to run on a microengine. Microblocks can be one <strong>of</strong> three types:<br />
— Source microblocks receive packet buffers from outside the microengine.<br />
— Transform microblocks operate on packet buffers and pass them on to other<br />
microblocks.<br />
Writing Micro<strong>ACE</strong>s 55<br />
Revision 3.3, August 2001
Micro<strong>ACE</strong> Architectural Elements<br />
l<br />
— Sink microblocks send packet buffers out <strong>of</strong> the microengine.<br />
Each microblock is associated with a core component, which you write in C/C++<br />
and NCL to run on the core processor. The core component is a complete <strong>ACE</strong><br />
with additional elements that initialize and manage the microblock component.<br />
Interface <strong>ACE</strong>s are implemented as micro<strong>ACE</strong>s with source (Rx) and sink (Tx)<br />
microblocks. You use the interface micro<strong>ACE</strong>s to receive and transmit packets<br />
through the network interface ports.<br />
You typically combine micro<strong>ACE</strong>s with conventional <strong>ACE</strong>s in an application. You<br />
can combine the interface micro<strong>ACE</strong>s with micro<strong>ACE</strong> building blocks that are<br />
provided by <strong>Intel</strong>, that you write yourself, or that are provided by third parties. The<br />
<strong>IXA</strong> <strong>SDK</strong> provides source files for sample applications that use the system and library<br />
<strong>ACE</strong>s in various configurations, in the following location:<br />
<strong>SDK</strong>installpath/src/microace/apps<br />
To develop microcode and build microcode images, use the IXP1200 Microengine<br />
Development Environment. The source files for the micro<strong>ACE</strong>s and dispatch loop<br />
that form a microcode image are collected into a single project file with the extension<br />
.dwp. For information on using the microengine development tools and microcode<br />
reference information, see the IXP1200 documentation set.<br />
Micro<strong>ACE</strong> Architectural Elements<br />
A micro<strong>ACE</strong> combines a core component, which runs on the core processor, with a<br />
microblock, written in microcode to run on a microengine.<br />
l<br />
l<br />
l<br />
l<br />
l<br />
A management program loads and configures micro<strong>ACE</strong>s along with the conventional<br />
<strong>ACE</strong>s for an application.<br />
The management program initializes the micro<strong>ACE</strong> Resource Manager, which<br />
deals with resource allocation, packet demultiplexing, and other system-level<br />
microengine management problems.<br />
Several microblocks are typically combined into a single microengine image<br />
called a microblock group. Each <strong>of</strong> the microblocks in a group is associated with<br />
exactly one core component.<br />
A microcode dispatch loop for each microengine initializes the microblocks in a<br />
group and determines how packets flow into, among, and out <strong>of</strong> the microblocks.<br />
The management program creates static binding among the micro<strong>ACE</strong>s to match<br />
the packet flow among microblocks in each group, as determined by the dispatch<br />
loop. Together, the microblock group and their linked core components form a<br />
micro<strong>ACE</strong> group.<br />
56 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Micro<strong>ACE</strong> Architectural Elements<br />
Architecture<br />
Summary<br />
The following table provides a brief description <strong>of</strong> each element in the micro<strong>ACE</strong><br />
architecture. The remaining sections <strong>of</strong> this chapter go into more detail on each <strong>of</strong> the<br />
elements.<br />
Element<br />
Management program<br />
Resource Manager<br />
Core component<br />
Microblock<br />
Microblock group<br />
Description<br />
A part <strong>of</strong> your application written in C/C++ that starts the<br />
micro<strong>ACE</strong>s along with the conventional <strong>ACE</strong>s for an application,<br />
performing all necessary configuration. Either a management<br />
program or a startup script must initialize <strong>ACE</strong>s,<br />
load and start the microcode images on the microengines,<br />
and set up micro<strong>ACE</strong> bindings to match the way that the dispatch<br />
loop has configured the processing sequence in each<br />
microblock group.<br />
System s<strong>of</strong>tware that provides a set <strong>of</strong> resources for the <strong>ACE</strong><br />
and micro<strong>ACE</strong> management program to use in managing the<br />
microengine memory and shared state. Also provides the<br />
run-time component for handling exception processing.<br />
An <strong>ACE</strong>, written in C/C++ and NCL, that manages a microblock<br />
in addition to classifying and acting on packets.<br />
The <strong>ACE</strong> maintains shared state between itself and its associated<br />
microblock. It acts as a crosscall server and exports a<br />
crosscall interface for management <strong>of</strong> the microblock.<br />
The core component receives exception packets from its<br />
microblock, processes them, and sends them to the appropriate<br />
targets. The core component can also receive packets<br />
from other <strong>ACE</strong>s whose targets are bound to it and send them<br />
down to its microblock for processing.<br />
The core component <strong>of</strong> a micro<strong>ACE</strong> must always have one<br />
static target bound to the micro<strong>ACE</strong> containing the next<br />
microblock in the dispatch loop’s processing sequence.<br />
A microcode macro that provides the acceleration component<br />
<strong>of</strong> a micro<strong>ACE</strong>. Typically processes the most common cases<br />
<strong>of</strong> packet forwarding and passes exception case packets to<br />
the core component for further processing.<br />
A microblock can act as a packet source or sink, or it can<br />
transform packets.<br />
One or more microblocks that have been combined into a single<br />
microengine image.<br />
When you compile a microblock group, the microcode<br />
assembler produces an image file with the extension.u<strong>of</strong>.<br />
The management program loads this image onto a specific<br />
microengine during initialization.<br />
This allows several stages <strong>of</strong> processing to occur on a single<br />
microengine. Typically all threads on the microengine execute<br />
the same microblock group. You can load the same<br />
microblock group on more than one microengine.<br />
Writing Micro<strong>ACE</strong>s 57<br />
Revision 3.3, August 2001
Loading Micro<strong>ACE</strong>s<br />
Element<br />
Dispatch loop<br />
Description<br />
For each microblock group, you write a microcode dispatch<br />
loop to implement the packet flow within the group. The dispatch<br />
loop configures the microblocks in the group into a processing<br />
pipeline.<br />
The loop for each microblock group starts with a packet<br />
source microblock, ends with a packet sink, and can have one<br />
or more transform microblocks in between.<br />
Microcode image<br />
The compiled single object (.u<strong>of</strong> file) that contains the<br />
microblocks in a group and the dispatch loop that defines the<br />
processing pipeline.<br />
Loading Micro<strong>ACE</strong>s<br />
The management program for an application or a startup script must load and start<br />
the <strong>ACE</strong>s and set target bindings. In addition, to load and start micro<strong>ACE</strong>s (including<br />
the interface <strong>ACE</strong>s), the management program or script must do the following:<br />
1. Initialize the Resource Manager using the function RmInit. An application must<br />
do this once before making any other calls to the Resource Manager. The Resource<br />
Manager initializes the hardware.<br />
2. Configure the ports using the function RmSetPortConfig, passing information on<br />
which ports need to be enabled.<br />
You can examine the port configuration that the Resource Manager sets up using<br />
RmUengGetConfig. You can use RmUengSetConfig instead <strong>of</strong> RmSetPortConfig<br />
to configure each microengine individually, or to change the configuration.<br />
3. Use the function RmUengSetUcode to write each compiled microcode image to the<br />
Resource Manager before launching the micro<strong>ACE</strong>s. An image is a .u<strong>of</strong> file<br />
containing the microblock group and dispatch loop for one microengine.<br />
4. Launch the micro<strong>ACE</strong>s using the function RmCreateMicroAce. Like<br />
ix_res_create_ace, this function calls the <strong>ACE</strong>’s initialization function,<br />
ix_init. Each micro<strong>ACE</strong>’s initialization routine must:<br />
a. Register with the Resource Manager using the function RmRegister.<br />
a. Patch variables into the microcode image using the function RmUengPatch-<br />
Symbols.<br />
b. Create at least one target to be statically bound to the micro<strong>ACE</strong> containing the<br />
next microblock in the group.<br />
5. Bind static targets among the micro<strong>ACE</strong>s to match the dispatch loop’s processing<br />
pipeline, using the function RmBindMicroAce.<br />
6. Bind any conventional targets among the micro<strong>ACE</strong>s and other <strong>ACE</strong>s using the<br />
Resolver function ix_res_bind.<br />
7. After launching the micro<strong>ACE</strong>s, load the microcode images for each microengine<br />
using the function RmUengLoad.<br />
58 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Loading Micro<strong>ACE</strong>s<br />
8. Start the micro<strong>ACE</strong> code running on each microengine using the function RmUengEnable.<br />
9. Configure the micro<strong>ACE</strong>s using their startup scripts or crosscalls.<br />
For more information on startup scripts and configuration files, see Chapter 4,<br />
“Configuring and Starting <strong>IXA</strong> Systems.”<br />
For a complete description <strong>of</strong> the Resource Manager and Resolver API functions, see<br />
the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Setting Up a<br />
Processing<br />
Pipeline for<br />
Micro<strong>ACE</strong>s<br />
The microblocks in a single image (a microblock group) form a packet-processing<br />
pipeline on a microengine. Packets come in through the input media interfaces, are<br />
processed by a series <strong>of</strong> microblocks, and are sent out through the output media interfaces,<br />
or on to another microblock group on another microengine.<br />
The dispatch loop’s microcode defines the packet flow among the microblocks in a<br />
group. The packet flow is fixed when you compile the microblocks and dispatch loop<br />
to generate a .u<strong>of</strong> microcode image. You cannot change the packet flow at run time.<br />
After processing a packet, a microblock returns a value to the dispatch loop. The<br />
dispatch loop uses the returned value to determine the disposition <strong>of</strong> the current<br />
packet. The microblock can tell the loop to send packets to:<br />
l<br />
l<br />
l<br />
The next microblock in the group<br />
Its own core component on the core processor<br />
Another microblock group<br />
port<br />
microblock<br />
port<br />
microblock<br />
Packet flow<br />
microblock<br />
Microengine<br />
microblock<br />
microblock<br />
Microengine<br />
Writing Micro<strong>ACE</strong>s 59<br />
Revision 3.3, August 2001
Loading Micro<strong>ACE</strong>s<br />
Creating Static Bindings<br />
For each microblock group, the management program must bind targets in the core<br />
components to correspond to the microblock packet flow implemented by the<br />
dispatch loop. Unlike the bindings <strong>of</strong> conventional targets and <strong>ACE</strong>s, you cannot<br />
change these bindings at run time; they are static.<br />
Core processor<br />
Static Resource Manager bindings<br />
core component a<br />
core component b<br />
Resource Manager<br />
port<br />
Packet flow in dispatch loop<br />
microblock a<br />
microblock b<br />
Microengine<br />
port<br />
A special Resource Manager function, RMBindMicroAce, creates the static bindings.<br />
Like the Resolver function ix_res_bind, this function requires an open Resolver<br />
session. The system does not provide any special target for the static binding; you can<br />
create a target for this purpose, or you can use the default target. For example, if you<br />
create a target named static in micro<strong>ACE</strong> a as shown in the figure, create the static<br />
binding to micro<strong>ACE</strong> b in the ixsys.config system configuration file:<br />
bind static a/static b<br />
If you write your own startup management program, use the Resource Manager<br />
function:<br />
RMBindMicroAce (myResolverSession, "/a/static", "/b");<br />
You can create additional targets in the micro<strong>ACE</strong>, bind them to other conventional<br />
<strong>ACE</strong>s or micro<strong>ACE</strong>s, and send packets to those targets. Similarly, you can bind<br />
targets in other <strong>ACE</strong>s to the micro<strong>ACE</strong> so that it can receive packets from them.<br />
Example<br />
The following pseudocode example <strong>of</strong> an <strong>ACE</strong> management program loads<br />
micro<strong>ACE</strong>s as well as conventional <strong>ACE</strong>s for an application, and sets their bindings,<br />
using Resource Manager API calls.<br />
int main(int argc, char**argv)<br />
{<br />
// Initialize the Resource Manager<br />
RmInit(...);<br />
// Set the port configuration<br />
RmSetPortConfig(...);<br />
// Set the microcode image onto each microengine<br />
for (i = 0; i < MAX_NUM_UENG; i++)<br />
RmUengSetUcode(...);<br />
60 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
// Launch micro<strong>ACE</strong>S. This call is synchronous; by the time it<br />
// returns, the ix_init() <strong>of</strong> the micro<strong>ACE</strong> has been called. The //<br />
program assumes that all imported variables<br />
// were patched in by ix_init()<br />
for (i = 0; i < numberOfMicroaces; i++)<br />
RmCreateMicroAce(...);<br />
// Launch conventional <strong>ACE</strong>S<br />
for (i = 0; i < numberOfRegularAces; i++)<br />
ix_res_create_ace(...);<br />
// Configure the micro<strong>ACE</strong>s and <strong>ACE</strong>s with crosscalls<br />
Configure<strong>ACE</strong>s(...)<br />
// bind the micro<strong>ACE</strong>s together with static targets<br />
for (i = 0; i < numberOfStaticBinds; i++)<br />
RmBindMicroAce(...);<br />
// bind micro<strong>ACE</strong>s and other <strong>ACE</strong>s with regular targets<br />
for (i = 0; i < numberOfRegularBinds; i++)<br />
ix_res_bind(...);<br />
// Load the microcode<br />
RmUengLoad(...);<br />
// Enable the microengines<br />
RmUengEnable(...);<br />
// Loop forever<br />
while (1);<br />
}<br />
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
The core component runs on the core processor, and performs the following functions<br />
for the micro<strong>ACE</strong>:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Exports <strong>IXA</strong> IDL interfaces to allow applications to configure the micro<strong>ACE</strong>.<br />
Allocates and sets up an SRAM control block to communicate with its associated<br />
microblock running on the microengines.<br />
Allocates and sets up tables and other data structures used by its associated<br />
microblock.<br />
Binds (patches) imported variables in the microcode to appropriate values during<br />
initialization.<br />
Receives exception packets from its associated microblock and processes them<br />
like a conventional <strong>ACE</strong>, using NCL and ASL.<br />
Handles packets received from other <strong>ACE</strong>s, sending them to its associated<br />
microblock on the microengines or to other targets.<br />
Like a conventional <strong>ACE</strong>, the C source code for the core component <strong>of</strong> a micro<strong>ACE</strong><br />
must define an initialization routine, ix_init, and a termination routine, ix_fini.<br />
See “Initializing a Micro<strong>ACE</strong>” on page 62 and “Terminating a Micro<strong>ACE</strong>” on<br />
page 64.<br />
Revision 3.3, August 2001<br />
Writing Micro<strong>ACE</strong>s 61
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
A micro<strong>ACE</strong> can contain conventional targets and the application can bind them to<br />
other <strong>ACE</strong>s or micro<strong>ACE</strong>s in order to pass packets to them. Similarly, an application<br />
can bind another <strong>ACE</strong>’s target to the micro<strong>ACE</strong> in order to send it packets. Like<br />
conventional <strong>ACE</strong>s, micro<strong>ACE</strong>s can use the default action function,<br />
ix_action_default, to handle packets by sending them to the default target.<br />
Exception<br />
Packet<br />
Handling<br />
The core component <strong>of</strong> a micro<strong>ACE</strong> handles exception packets that the microblock<br />
cannot process, using an application-defined exception handler.<br />
During the processing <strong>of</strong> a packet buffer, an exceptional condition might occur that<br />
requires additional processing. In this case, the microblock sends the buffer to its core<br />
processor core component by returning the special value IX_EXCEPTION to the<br />
dispatch loop. It passes an additional application-defined code along with the packet<br />
buffer to indicate what type <strong>of</strong> exception occurred.<br />
When the exception occurs, the dispatch loop places the buffer into a queue going to<br />
the core processor. All microblocks in a group share the queue. To identify the<br />
micro<strong>ACE</strong> that flagged the exception and will handle it, the dispatch loop uses the<br />
<strong>ACE</strong> tag, which is assigned by the RmRegister function when you initialize and start<br />
the micro<strong>ACE</strong>. The <strong>ACE</strong> tag has the form microblockName_TAG. After it has set the<br />
<strong>ACE</strong> tag, the dispatch loop can use the macro DL_SASink to send the packet up.<br />
The C source code for the core component <strong>of</strong> a micro<strong>ACE</strong> must define a handler<br />
routine for exception packets received from the associated microblock. See “Writing<br />
an Exception Packet Handler” on page 64.<br />
Initializing a<br />
Micro<strong>ACE</strong><br />
A management program launches a micro<strong>ACE</strong> using the Resource Manager function<br />
RmCreateMicroAce, which is similar to the Resolver function for creating conventional<br />
<strong>ACE</strong>s, ix_res_create_ace. Like the Resolver function, it requires an active<br />
Resolver session. See the <strong>IXA</strong> <strong>SDK</strong> Reference for details <strong>of</strong> these functions.<br />
Like conventional <strong>ACE</strong>s, the core component <strong>of</strong> a micro<strong>ACE</strong> must define an initialization<br />
routine, ix_init. When you launch the micro<strong>ACE</strong>, the creation function calls<br />
the ix_init function that is defined in the source code specified for the new<br />
micro<strong>ACE</strong>. The creation function passes down command-line arguments to ix_init.<br />
Micro<strong>ACE</strong>s must use the following convention for command-line arguments:<br />
Argument Description<br />
argv[0]<br />
Name <strong>of</strong> the executable.<br />
argv[1] Name <strong>of</strong> the <strong>ACE</strong>.<br />
argv[2]<br />
A bit mask indicating the microengines on which the microblock for this<br />
<strong>ACE</strong> runs. The 6 least significant bits <strong>of</strong> the microengine mask are used.<br />
The microengines are numbered 0-5.<br />
In addition to those things that it does for a conventional <strong>ACE</strong> (creating the ix_ace<br />
structure, calling ix_ace_init, creating related structures such as targets and sets,<br />
and initializing the <strong>ACE</strong> as a crosscall server and/or client), the ix_init initialization<br />
routine for a micro<strong>ACE</strong> must do the following:<br />
62 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
l<br />
l<br />
l<br />
Register the new micro<strong>ACE</strong> with the Resource Manager using the function<br />
RmRegister. This assigns the <strong>ACE</strong> tag that associates the microblock with the core<br />
component.<br />
Patch any imported variables for this micro<strong>ACE</strong> into the microblock, using the<br />
function RmUengPatchSymbols. After the micro<strong>ACE</strong> initialization routine returns,<br />
no more symbols can be patched. Symbols must be patched for all micro<strong>ACE</strong>s<br />
before the management program can load and start the microcode image.<br />
Use the Resource Manager to allocate memory in SRAM for the control block, and<br />
other shared memory (SRAM, SDRAM, or scratch) for any data structures to be<br />
shared with the microengines. See “Allocating Memory for Shared Data” on<br />
page 65.<br />
Initialization Example<br />
The following is a pseudocode example <strong>of</strong> a micro<strong>ACE</strong> initialization routine.<br />
ix_error ix_init (int argc, char** argv, ix_ace **acepp)<br />
{<br />
// Allocate <strong>ACE</strong> structure, get <strong>ACE</strong> name and initialize <strong>ACE</strong><br />
*acepp = malloc(...)<br />
name = argv[1]<br />
ix_ace_init(*acepp, name)<br />
// Initialize the Resource Manager<br />
RmInit(...)<br />
// Allocate SRAM for control block<br />
controlBlock = RmMalloc(...)<br />
// Allocate SRAM/SDRAM/SCRATCH for other data structures<br />
otherMemory = RmMalloc(...)<br />
// Set up these data structures<br />
SetupDataStructures(...)<br />
// Register an exception handler with the Resource Manager<br />
// and get a unique tag for the microblock. This tag can be used<br />
// to sendpackets to the microblock<br />
RmRegister(...)<br />
// Get the microengine mask for this <strong>ACE</strong><br />
meMask = atoi(argv[2])<br />
// For each microengine in the mask, patch variables<br />
// for this <strong>ACE</strong><br />
for (i = 0; i < numberOfImportedVariables; i++)<br />
RmUengpatchSymbol(...)<br />
// Other <strong>ACE</strong>-specific actions, such as creating targets<br />
return 0;<br />
}<br />
Writing Micro<strong>ACE</strong>s 63<br />
Revision 3.3, August 2001
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
Terminating a<br />
Micro<strong>ACE</strong><br />
Like conventional <strong>ACE</strong>s, the core component <strong>of</strong> a micro<strong>ACE</strong> must define an termination<br />
routine, ix_fini. When an application stops a micro<strong>ACE</strong>, the Resource Manager<br />
calls the ix_fini function defined in that <strong>ACE</strong>’s executable. See the <strong>IXA</strong> <strong>SDK</strong> Reference<br />
for details <strong>of</strong> the ix_fini function.<br />
In addition to those actions it takes for a conventional <strong>ACE</strong> (calling the ix_ace_fini<br />
function and freeing the memory allocated for the ix_ace structure), the ix_fini<br />
function for a micro<strong>ACE</strong> must do the following:<br />
l<br />
l<br />
Unregister from the Resource Manager<br />
Free all allocated Resource Manager memory<br />
Termination Example<br />
The following is a pseudocode example <strong>of</strong> a micro<strong>ACE</strong> termination routine:<br />
ix_error ix_fini (int argc, char**argv, ix_ace *acep)<br />
{<br />
// Unregister from the Resource Manager<br />
RmUnRegister(...)<br />
// Free all Resource Manager memory<br />
RmFree(...)<br />
// Terminate the path to the Resource Manager<br />
RmTerm(...)<br />
// Call the ix_ace_fini() function<br />
ix_ace_fini(...)<br />
// Free <strong>ACE</strong> structure and other memory allocated in ix_init<br />
free(...)<br />
}<br />
Writing an<br />
Exception<br />
Packet Handler<br />
The core component <strong>of</strong> a micro<strong>ACE</strong> typically defines a routine to handle exception<br />
packets received from the microblock.<br />
l<br />
l<br />
When you register the micro<strong>ACE</strong> during initialization using the Resource<br />
Manager function RmRegister, pass a pointer to the exception handler function,<br />
which you define in the C/C++ source code for the <strong>ACE</strong>.<br />
The Resource Manager calls the designated exception handler function once for<br />
every exception packet that the microblock identifies.<br />
Each exception packet the microblock sends up is associated with an exception code<br />
to indicate the reason for the exception. The exception handler must call the Resource<br />
Manager function RmGetExceptionCode to retrieve this exception code. Your application<br />
defines the exception codes and their meanings.<br />
The handler routine typically processes the packet and disposes <strong>of</strong> it. It can:<br />
l<br />
Send it back to the microblock for further processing using the Resource Manager<br />
function RmSend.<br />
64 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
l<br />
l<br />
l<br />
Send it to another <strong>ACE</strong> through a conventional target.<br />
Send it to another micro<strong>ACE</strong> through a static target; in this case, the packet is<br />
received by the core component <strong>of</strong> the micro<strong>ACE</strong>, which will send the packet<br />
buffer down to its associated microblock for processing. By convention, you do<br />
not send a packet buffer directly to the microblock <strong>of</strong> another micro<strong>ACE</strong>.<br />
Discard the packet and free the packet buffer.<br />
Exception Packet Handler Example<br />
The following is a pseudocode example <strong>of</strong> an exception handling routine:<br />
int ExceptionPacketHandler (void *ctxp,<br />
ix_ring ring,<br />
ix_buffer buffer)<br />
{<br />
ix_ace* acep = (ix_ace*) ctxp;<br />
// Get the exception code for this packet.<br />
RmGetExceptionCode(...)<br />
// Process the packet and either send it to a target,<br />
// drop it, or use RmSend to send it back to the microblock<br />
...<br />
return 0;<br />
}<br />
Allocating<br />
Memory for<br />
Shared Data<br />
The microengines and core processor share access to three types and areas <strong>of</strong><br />
memory:<br />
l<br />
l<br />
l<br />
uncached SDRAM<br />
SRAM<br />
cache memory (also called scratch memory)<br />
Some <strong>of</strong> the shared memory is used by the <strong>IXA</strong> system s<strong>of</strong>tware and operating<br />
system, but a portion <strong>of</strong> it is available to micro<strong>ACE</strong>s through the Resource Manager.<br />
ASL (16 Mb)<br />
Resource Manager<br />
(48 Mb)<br />
Shared memory for the IXP1200 Evaluation Platform<br />
Linux (64 Mb)<br />
SDRAM<br />
ASL (1 Mb)<br />
Resource Manager<br />
(3 Mb)<br />
SRAM<br />
Resource Manager<br />
(4 Kb)<br />
Scratch<br />
Writing Micro<strong>ACE</strong>s 65<br />
Revision 3.3, August 2001
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
While conventional <strong>ACE</strong>s define sets and searches to access application data, the<br />
microengines cannot access sets. If a micro<strong>ACE</strong> must store and access data, it must<br />
allocate a table in shared memory. The Resource Manager API provides a simple<br />
memory management mechanism, which you use for coarse-grained static allocation.<br />
Use the operating system to do fine-grained, dynamic memory management<br />
within the core component.<br />
Use the following Resource Manager API functions to manage memory for<br />
micro<strong>ACE</strong> data structures that the core component shares with the microblock:<br />
Function<br />
RmMalloc<br />
RmFree<br />
RmRead<br />
RmWrite<br />
RmGetPhysOffset<br />
RmGetBufferPtr<br />
RmGetMemInfo<br />
Description<br />
Allocates memory <strong>of</strong> a particular type (SDRAM, SRAM, or<br />
scratch) for the Resource Manager.<br />
Frees memory <strong>of</strong> a particular type in Resource Manager<br />
memory.<br />
Reads memory allocated by RmMalloc.<br />
Writes to memory allocated by RmMalloc.<br />
Retrieves the physical word <strong>of</strong>fset from start <strong>of</strong> memory for a<br />
segment allocated by RmMalloc.<br />
Retrieves the buffer pointer for memory allocated by the<br />
RmMalloc function.<br />
Retrieves the free-memory statistics.<br />
For details <strong>of</strong> how to use these functions, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Once the core component has set up and initialized data structures in shared memory,<br />
both the core component and microblock must define a mechanism for accessing the<br />
data. In the microblock, you can use the hardware hashing mechanism built into the<br />
IXP1200 network processor to hash into the data tables and reduce the search space.<br />
In order to duplicate these hash values in the core component, the ASL provides a set<br />
<strong>of</strong> hash functions that use the same hashing algorithm. For details <strong>of</strong> the ASL hash<br />
functions, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Shared<br />
Memory Table<br />
Example<br />
The following example shows both sides (microengine and core processor) <strong>of</strong> how<br />
you might allocate a table in shared memory and access it with hash values.<br />
Microcode Side: Hash Initialization and Table Implementation<br />
/* Setting up Hash Table */<br />
mul = MULT ;<br />
ECK(ix_hash64_init(&h64)) ;<br />
ECK(ix_hash64_set_mult(&h64, mul)) ;<br />
/* Microblock Table Implementation */<br />
#macro calculate_hash[key, ipsrc, ipdst, sport, dport, proto]<br />
.local $hash0 $hash1 $hash2 $hash3 $hash4 tmp<br />
.xfer_order $hash0 $hash1 $hash2 $hash3<br />
66 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing the Core Component <strong>of</strong> a Micro<strong>ACE</strong><br />
; Setup the hash unit<br />
;<br />
immed[$hash4, MULT]<br />
csr[write, $hash4, hash_multiplier_64_lo], ctx_swap<br />
; setup the hash keys<br />
move[$hash0, sport]<br />
ld_field[$hash0, 1100, proto, protocol, tuple->dest_port,<br />
tuple->dest_add ) ;<br />
combined_key = key1 ^ key2 ;<br />
Index = TABLE_MASK ;<br />
Index = combined_key & TABLE_MASK;<br />
return Index ;<br />
Writing Micro<strong>ACE</strong>s 67<br />
Revision 3.3, August 2001
Configuring Micro<strong>ACE</strong>s with Crosscalls<br />
}<br />
ix_64bit hash_64( ix_16bit protocol, ix_16bit port,<br />
ix_32bit address )<br />
{<br />
ix_64bit val, key ;<br />
val = 0 ;<br />
key = ((ix_64bit)address) | (((ix_64bit)port)
Microblock Types and Groups<br />
You write a microblock as a microcode macro. Each microblock makes use <strong>of</strong> the<br />
dispatch loop global variables and macros to pass packet buffers and information.<br />
See “Writing a Dispatch Loop” on page 71.<br />
Packet buffers generally flow into the microblock group from a network interface<br />
port. A core component can also send packets down to its own microblock—the<br />
dispatch loop handles packets that come from the core components, steering them to<br />
the appropriate microblock.<br />
A microblock can send packets to the core component <strong>of</strong> its micro<strong>ACE</strong>, or to other<br />
microblocks in the group by returning values to the dispatch loop. The dispatch loop<br />
acts on the return values to define the flow <strong>of</strong> packets within and out <strong>of</strong> the group.<br />
Microblock<br />
Types<br />
There are three types <strong>of</strong> microblocks:<br />
l<br />
l<br />
l<br />
Source microblocks get the packets to be processed by the rest <strong>of</strong> the pipeline.<br />
Examples <strong>of</strong> source microblocks include those that read data from network interface<br />
ports or those that schedule packets for transmission from a set <strong>of</strong> queues.<br />
Transform microblocks process a packet and pass it to the next microblock. Transform<br />
microblocks can modify the buffer data, gather statistics on the buffer<br />
contents, or steer the buffer between multiple code blocks.<br />
Sink microblocks dispose <strong>of</strong> packets within the microblock group. Disposal<br />
actions can include queuing packets to another microblock or to the core component<br />
for further processing or transmitting the packet on a network interface port.<br />
Source Microblocks<br />
Source microblocks are responsible for obtaining the next packet buffer to be<br />
processed. The first microblock to run in a microblock group is the source microblock.<br />
Implement each source microblock as a macro with the following format:<br />
source_block []<br />
The source microblock must do the following:<br />
1. Set the global variable dl_buffer_handle to a valid handle, or to<br />
IX_BUFFER_NULL if there is no buffer to process.<br />
2. Set the buffer length, buffer <strong>of</strong>fset, and the input port variables using the dispatch<br />
loop macros. See “Defining Additional Global Registers” on page 73.<br />
3. If desired, set the receive status flags and the IXP1200 fast port sequence number<br />
if the buffer was received from a fast port.<br />
The microblock <strong>of</strong> an input interface micro<strong>ACE</strong> is an example <strong>of</strong> a source microblock.<br />
This code removes mpackets (the internal unit <strong>of</strong> transfer) from the IX Bus and reassembles<br />
them into a packet buffer. If the current mpacket completes a frame, the code<br />
returns the pointer to the completed buffer. If the frame is not complete, it returns<br />
IX_BUFFER_NULL.<br />
An application-defined source microblock would get the next packet buffer from the<br />
queue where it was passed from another microblock group, and set the buffer handle<br />
to point to it. If no packet buffers are in the queue, it returns IX_BUFFER_NULL.<br />
Writing Micro<strong>ACE</strong>s 69<br />
Revision 3.3, August 2001
Microblock Types and Groups<br />
Transform Microblocks<br />
Transform microblocks perform basic packet operations. Some typical operations<br />
include IP forwarding, NAT, and filtering. The transform microblock operates on the<br />
packet buffer and returns an indication <strong>of</strong> how the packet buffer should be processed<br />
next. Any number <strong>of</strong> transform microblocks can run between the source and sink<br />
microblocks in a microblock group. Implement each transform microblock as a macro<br />
with the following format:<br />
transform_block []<br />
The transform microblock must do the following:<br />
1. Get the current packet buffer handle from the dispatch loop global variable<br />
dl_buffer_handle.<br />
2. Process the packet buffer.<br />
3. Set the value <strong>of</strong> the global variable dl_next_block to tell the dispatch loop where<br />
to send the packet buffer next.<br />
— For fast-path processing, set the variable to the number <strong>of</strong> the next microblock<br />
in the group. Your application defines the microblock numbers.<br />
— For exception cases, set the variable to IX_EXCEPTION to send the buffer to the<br />
transform microblock’s core component. You can pass an exception code with<br />
the packet using the dispatch loop macros.<br />
The microblocks <strong>of</strong> the library <strong>ACE</strong>s are examples <strong>of</strong> transform microblocks.<br />
Sink Microblocks<br />
Sink microblocks are responsible for disposing <strong>of</strong> packet buffers. The last microblock<br />
executed in a microblock group for a given packet buffer is a sink microblock. Implement<br />
each sink microblock as a macro with the following format:<br />
sink_block[]<br />
The sink microblock must do the following:<br />
1. Get the handle to the current packet buffer from the global dispatch loop variable<br />
dl_buffer_handle.<br />
2. If desired, use the dispatch loop macros to get the output port number for the<br />
buffer being processed.<br />
The microblock <strong>of</strong> an output interface micro<strong>ACE</strong> is an example <strong>of</strong> a sink microblock.<br />
This code disassembles a packet buffer into mpackets (the internal unit <strong>of</strong> transfer)<br />
for transmission through a network interface port.<br />
An application-defined sink microblock would queue the packet buffer for<br />
processing by another microblock group.<br />
Examples <strong>of</strong><br />
Microblocks<br />
Typical microblocks for micro<strong>ACE</strong>s can include the following:<br />
70 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing a Dispatch Loop<br />
Block Type Description<br />
Slow Ethernet<br />
Ingress<br />
Fast Ethernet<br />
Ingress<br />
source<br />
source<br />
Reads mpackets from the IX bus and reassembles<br />
them into a packet buffer. When it has a complete<br />
buffer, it returns the handle for further processing. It<br />
can perform link-level filtering as appropriate.<br />
This microblock is used by the input interface <strong>ACE</strong><br />
for this type <strong>of</strong> port.<br />
Similar to the Slow Ethernet Ingress, but handles<br />
the fast (gigabit) Ethernet ports.<br />
This microblock is used by the input interface <strong>ACE</strong><br />
for this type <strong>of</strong> port.<br />
IP Forward transform Performs the destination route lookup and the modifications<br />
needed for forwarding the buffer.<br />
Flow Processor transform Processes packets based on a set <strong>of</strong> tables, using<br />
the 5-tuple that identifies each TCP/UDP connection.<br />
Provides filtering and NAT.<br />
Sink Packet sink Queues packets to be processed by another<br />
microblock group.<br />
Slow Ethernet<br />
Transmit<br />
Fast Ethernet<br />
Transmit<br />
sink<br />
sink<br />
Transmits packet buffers out slow (10/100) Ethernet<br />
ports.<br />
This microblock is used by the output interface <strong>ACE</strong><br />
for this type <strong>of</strong> port.<br />
Transmits packet buffers out fast (gigabit) Ethernet<br />
ports.<br />
This microblock is used by the output interface <strong>ACE</strong><br />
for this type <strong>of</strong> port.<br />
Writing a Dispatch Loop<br />
The packet flow within a microblock group is defined by the microcode dispatch loop<br />
that you provide. You link the dispatch loop with the microblocks in the group to<br />
compile the microcode image (.u<strong>of</strong> file) for each microblock group.<br />
l<br />
l<br />
l<br />
The dispatch loop first initializes each microblock in the group, then handles<br />
packets that have been sent down from the core components on the core<br />
processor, passing them to the proper associated microblocks.<br />
The dispatch loop caches common variables in registers that the microblocks can<br />
access either directly or using a set <strong>of</strong> predefined helper macros.<br />
The main portion <strong>of</strong> the dispatch loop describes the packet flow among the<br />
micro<strong>ACE</strong>s that are part <strong>of</strong> the microblock group.<br />
Writing Micro<strong>ACE</strong>s 71<br />
Revision 3.3, August 2001
Writing a Dispatch Loop<br />
Microblocks in the group return values to the dispatch loop by setting the global variables.<br />
The dispatch loop acts on the return values to define the flow <strong>of</strong> packets within<br />
and out <strong>of</strong> the group.<br />
The dispatch loop can use system-defined macros to transfer packets to and from the<br />
core processor, to send packets to a different microblock group, to access global variables,<br />
and to manipulate packet buffers. The predefined macros are listed and<br />
described in Chapter 6, “Micro<strong>ACE</strong> Support Services,” <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Dispatch Loop<br />
Global<br />
Registers<br />
Each microblock directly sets and accesses the following global registers, which the<br />
dispatch loop can also access:<br />
Global Register<br />
Description<br />
dl_buffer_handle<br />
dl_next_block<br />
Stores a buffer handle for the current packet buffer.<br />
The source microblock at the top <strong>of</strong> the dispatch loop must<br />
set this register to a valid buffer handle or to<br />
IX_BUFFER_NULL.<br />
Stores the microblock return value.<br />
l To steer the packet buffer to the appropriate next transform<br />
microblock for processing, each transform microblock<br />
sets this register to the destination microblock’s<br />
application-defined number.<br />
l To send a packet buffer to the core component on the<br />
core processor, the transform microblock sets this register<br />
to IX_EXCEPTION.<br />
The dispatch loop caches commonly used variables such as thread ID, input and<br />
output port, and so on, in global registers. You must use a .local statement at the<br />
top <strong>of</strong> the dispatch loop to define the global registers for the buffer handle and return<br />
value, and any other registers that will be used by any microblock. For example:<br />
.local dl_buffer_handle dl_next_block dl_reg1 dl_reg2 dl_reg3<br />
The dispatch loop and microblocks can use a set <strong>of</strong> predefined helper macros to set<br />
and retrieve values from these registers, and to create and manipulate packet buffers.<br />
To use these, include the file:<br />
<strong>SDK</strong>installpath/src/microace/common/dispatchloops/<br />
DispatchLoop_h.uc<br />
The predefined macros are listed and described in detail in Chapter 6, “Micro<strong>ACE</strong><br />
Support Services,” <strong>of</strong> the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
72 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing a Dispatch Loop<br />
Defining Additional Global Registers<br />
Depending on register availability, a dispatch loop can define global registers for the<br />
use <strong>of</strong> a particular transform microblock, which are saved across iterations <strong>of</strong> the<br />
dispatch loop. The names <strong>of</strong> global registers that you define for a particular microblock<br />
must be prefixed with the name <strong>of</strong> that microblock, in the form<br />
blockName_regName—for example, wred_averageQueueSize.<br />
All other registers used by a microblock must be declared as .local within the<br />
microblock, as well as in the dispatch loop.<br />
Implementing<br />
Control Flow<br />
Each microblock sets the dl_next_block register, returning a numeric value that<br />
indicates which path a packet buffer should follow, or IX_EXCEPTION. (See<br />
“Returning Values to the Dispatch Loop” on page 75.) The dispatch loop checks the<br />
dl_next_block register and interprets the value. For example:<br />
IPFilter#:<br />
IPFilter[ ]<br />
.if (dl_next_block == 1)<br />
br[DL_MESink#]<br />
.else<br />
br[DL_Drop#]<br />
.endif<br />
The dispatch loop uses this mechanism to determine the sequence in which<br />
micro<strong>ACE</strong>s process packets. Because this sequence is compiled into the microcode<br />
image, it cannot be changed at run time. Your application must set up static target<br />
bindings for the micro<strong>ACE</strong>s to match the processing sequence in the dispatch loop.<br />
For more information, see Chapter 4, “Configuring and Starting <strong>IXA</strong> Systems,” and<br />
Chapter 5, “Controlling Packet Flow.”<br />
Dispatch Loop<br />
Example<br />
The following example shows a typical structure for a dispatch loop.<br />
The dispatch loop begins by declaring all the registers that will be used by the loop<br />
itself and by the microblocks for shared variables. The #include statements identify<br />
each microblock in the group.<br />
; declare global variables<br />
.local dl_buffer_handle dl_next_block dl_reg1 dl_reg2 dl_reg3<br />
; Include microblock source files<br />
#include "EthernetIngress.uc"<br />
#include "IPFilter.uc"<br />
#include "IPFwd.uc"<br />
The dispatch loop initializes each microblock in the group by calling the<br />
BlockName_Init[] macro.<br />
; Do initialization<br />
DL_Init[ ]<br />
EthernetIngress_Init[ ]<br />
IPFilter_Init[ ]<br />
IPFwd_Init[ ]<br />
Writing Micro<strong>ACE</strong>s 73<br />
Revision 3.3, August 2001
Writing a Dispatch Loop<br />
The first part <strong>of</strong> the dispatch loop dequeues packets coming from the core processor,<br />
passing them directly to the destination microblock.<br />
; Run the dispatch loop<br />
.while(1)<br />
; Consume packets from the SA.<br />
DL_SASource[ ]<br />
.if (dl_buffer_handle == IX_BUFFER_NULL)<br />
br[Main_Dispatch#]<br />
.elif (dl_next_block == IPFILTER_TAG)<br />
br[IPFilter#]<br />
.elif (dl_next_block == IPFWD_TAG)<br />
br[IPFwd#]<br />
.endif<br />
In this example, the dispatch loop has an Ethernet interface source microblock,<br />
followed by IPFilter and IPFwd transform microblocks. The microblocks return<br />
value by setting dl_next_block to indicate where to pass the packet next.<br />
; Main dispatch loop<br />
Main_Dispatch#:<br />
EthernetIngress[ ]<br />
.if (dl_buffer_handle == IX_BUFFER_NULL)<br />
.continue<br />
.endif<br />
.if (dl_next_block != 1)<br />
br[DL_Drop#]<br />
.else<br />
IPFilter#:<br />
IPFilter[ ]<br />
.if (dl_next_block == IX_EXCEPTION)<br />
.local ace_tag<br />
immed[ace_tag, IPFILTER_TAG]<br />
DL_SetAceTag[ace_tag]<br />
.endlocal<br />
br[DL_SASink#]<br />
.elif (dl_next_block == 1)<br />
IPFwd#:<br />
IPFwd[ ]<br />
.if (dl_next_block == IX_EXCEPTION)<br />
.local ace_tag<br />
immed[ace_tag, IPFWD_TAG]<br />
DL_SetAceTag[ace_tag]<br />
.endlocal<br />
br[DL_SASink#]<br />
.elif (dl_next_block == 1)<br />
br[DL_MESink#]<br />
.else<br />
br[DL_Drop#]<br />
.endif<br />
.else<br />
br[DL_Drop#]<br />
.endif<br />
.endif<br />
74 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Writing a Microblock<br />
DL_SASink#:<br />
DL_SASink[ ]<br />
.continue<br />
DL_MESink#:<br />
DL_MESink[ ]<br />
.continue<br />
DL_Drop#:<br />
DL_Drop[ ]<br />
.endw<br />
.endlocal<br />
Writing a Microblock<br />
A transform microblock performs whatever classification or processing is necessary<br />
on the current packet buffer, which it finds and stores in a global register. It then<br />
returns an application-defined value in another global register, that the dispatch loop<br />
uses to determine the further disposition <strong>of</strong> the packet buffer. Typically, it either<br />
transmits the packet or flags an exception so that the packet will be processed by the<br />
core component.<br />
Returning<br />
Values to the<br />
Dispatch Loop<br />
Each microblock can have one or more logical outputs, and returns a numeric value<br />
that indicates which path a packet buffer should follow. A microblock identifies the<br />
next destination microblock by setting dl_next_block to an application-defined<br />
number or to IX_EXCEPTION.<br />
l<br />
The return value IX_EXCEPTION is reserved to indicate that the buffer should be<br />
sent to the core component on the core processor for further processing.<br />
l By convention, each microblock numbers its other logical outputs starting at 1.<br />
When you write a microblock for reuse, you must document:<br />
— The number <strong>of</strong> logical outputs it has<br />
— The return values assigned to the outputs<br />
— The semantic meaning associated with the outputs<br />
Transmitting a<br />
Packet<br />
To transmit the current packet after processing, the microblock must do the<br />
following:<br />
1. Determine which network interface port to use for transmission, according to the<br />
application logic.<br />
2. Use the DL_SetOutputPort macro to set the port number in the packet.<br />
3. Set the global register dl_next_block to the application-defined code for transmission.<br />
For example, the following lines set up a fast-path packet for output on the first<br />
gigabit Ethernet port:<br />
Writing Micro<strong>ACE</strong>s 75<br />
Revision 3.3, August 2001
Writing a Microblock<br />
DL_SetOutputPort[16]<br />
immed[dl_next_block, 1]<br />
In this case, the dispatch loop must interpret the next-block value <strong>of</strong> 1 to mean that it<br />
should use the macro DL_MESink to transmit the packet. For example:<br />
.if (dl_next_block == 1)<br />
br[DL_MESink#]<br />
...<br />
DL_MESink#:<br />
DL_MESink[ ]<br />
.continue //return to top <strong>of</strong> dispatch loop<br />
The DL_MESink macro transfers the current packet to the microengine that is running<br />
a microcode image that contains an output interface <strong>ACE</strong> configured for the packet’s<br />
output port.<br />
Sending an<br />
Exception<br />
When an exception occurs, the transform microblock must do the following:<br />
1. Use the DL_SetExceptionCode macro to set the application-defined exception<br />
code<br />
2. Set the dl_next_block register to IX_EXCEPTION.<br />
The dispatch loop must do the following:<br />
1. Check for the next-block value <strong>of</strong> IX_EXCEPTION.<br />
2. Use the macro DL_SetAceTag to set the current <strong>ACE</strong> tag correctly for the microblock<br />
that flagged the exception.<br />
3. Use the macro DL_SASink to send the current packet buffer to the micro<strong>ACE</strong>’s<br />
core component (as identified by the <strong>ACE</strong> tag) for exception processing.<br />
The exception handler in the core component uses the Resource Manager function<br />
RmGetExceptionCode to retrieve the code set by the microblock.<br />
For example, the following lines from the L3 forwarder library <strong>ACE</strong>’s microblock set<br />
the exception code which that <strong>ACE</strong> defines for an ARP packet, then sets the exception<br />
flag in dl_next_block:<br />
immed32[exception_code, IPV4UNICASTFWD_EXCEPTION_ARP]<br />
DL_SetExceptionCode[exception_code]<br />
immed32[dl_next_block, IX_EXCEPTION]<br />
The following lines from a dispatch loop detect the exception state and send the<br />
exception packet to the core component <strong>of</strong> the L3Fwdr micro<strong>ACE</strong>:<br />
L3Fwdr#:<br />
L3Fwdr[ ] //sets exception code and flag<br />
.if (dl_next_block == IX_EXCEPTION)<br />
.local ace_tag<br />
immed[ace_tag, L3FWDR_TAG]<br />
DL_SetAceTag[ace_tag]<br />
.endlocal<br />
br[DL_SASink#]<br />
76 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Micro<strong>ACE</strong> Design Example<br />
.elif (dl_next_block == 1)<br />
DL_SASink#:<br />
DL_SASink[ ]<br />
.continue<br />
Micro<strong>ACE</strong> Design Example<br />
The following example shows how a layer 3 forwarding application uses micro<strong>ACE</strong>s.<br />
Core processor<br />
Stack <strong>ACE</strong><br />
Input IF <strong>ACE</strong><br />
configuration<br />
crosscalls<br />
L3Fwd<br />
<strong>ACE</strong><br />
Output IF <strong>ACE</strong><br />
Resource Manager<br />
port<br />
Input IF<br />
microblock<br />
exception<br />
packets<br />
L3Fwd<br />
microblock<br />
Output IF<br />
microblock<br />
port<br />
Packet flow<br />
Microengine<br />
This application, like most applications, uses the system-defined interface <strong>ACE</strong>s for<br />
input and output <strong>of</strong> packet buffers from and to the network interface ports. The interface<br />
<strong>ACE</strong>s are implemented as micro<strong>ACE</strong>s, with a core component and a microblock<br />
that communicate through the Resource Manager. Applications can configure the<br />
interface <strong>ACE</strong>s using their exported crosscalls.<br />
The application also makes use <strong>of</strong> the system-defined stack <strong>ACE</strong>, which passes<br />
packet buffers to and from the Linux * TCP/IP stack. The stack <strong>ACE</strong> is a conventional<br />
<strong>ACE</strong>.<br />
The application logic is in the L3Fwd micro<strong>ACE</strong>. The microblock component handles<br />
fast-path processing, forwarding packets based on a forwarding table. It sends exception<br />
packets (in this case, those with IP options in the header, fragmented packets,<br />
ARP and so on), to its core component.<br />
The Resource Manager, a piece <strong>of</strong> system s<strong>of</strong>tware running in the core processor<br />
kernel, passes configuration information and packet buffers between the core components<br />
<strong>of</strong> the micro<strong>ACE</strong>s and their associated microblocks.<br />
In addition to the <strong>ACE</strong>s and micro<strong>ACE</strong>s, the application includes:<br />
l A C management program that launches the micro<strong>ACE</strong>s and the stack <strong>ACE</strong>,<br />
binds them together, downloads microcode and enables the microengines.<br />
Writing Micro<strong>ACE</strong>s 77<br />
Revision 3.3, August 2001
Micro<strong>ACE</strong> Design Example<br />
l<br />
A microcode dispatch loop for each microengine that implements the data flow<br />
for that microengine and caches commonly used variables in registers. The<br />
dispatch loop sends and receives packets to and from the core processor and the<br />
other microengines.<br />
During application initialization, the management program binds the static<br />
micro<strong>ACE</strong> targets to reflect the flow <strong>of</strong> data in the dispatch loop. Once bound, they<br />
cannot be changed. The targets between the micro<strong>ACE</strong>s and the stack <strong>ACE</strong> are<br />
conventional targets and can be bound and unbound more than once.<br />
Packets flow through this application as follows:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
The microblock component <strong>of</strong> the input interface micro<strong>ACE</strong> gets a packet from a<br />
port. It sets the input port in a global register using a dispatch loop macro and<br />
passes all packets to the L3Fwd microblock.<br />
The L3Fwd microblock checks whether the packet is an IP packet, ARP packet, or<br />
some other type <strong>of</strong> packet. For every IP packet, the microblock validates the<br />
packet, dropping invalid packets.<br />
— If a packet is valid, but has options in the header, is fragmented, or is multicast<br />
it is considered an exception case and the microblock sends it to the L3Fwdr<br />
core component using the dispatch loop and the Resource Manager.<br />
— If a valid packet is not an exception case, the microblock finds the next-hop IP<br />
address and output port number in the forwarding table. It retrieves the destination<br />
MAC address <strong>of</strong> the next-hop IP and sets it for this packet. It then sets<br />
the output port number in a global register using a dispatch loop macro.<br />
The dispatch loop looks at the output port number in the global register and<br />
queues the valid, nonexception packet for output. There is one queue per port.<br />
The microblock for the output interface micro<strong>ACE</strong> dequeues the packet and sends<br />
it out over the appropriate port.<br />
For an exception packet, the L3Fwdr core component on the core processor<br />
processes the packet. It then takes one <strong>of</strong> the following actions:<br />
— Sends the packet to the output interface <strong>ACE</strong> using the conventional bound<br />
target. The core component <strong>of</strong> the interface <strong>ACE</strong> then sends the packet down<br />
to its own microblock using a Resource Manager call.<br />
— Sends the packet to the stack <strong>ACE</strong>, which processes the packet then sends it to<br />
the output interface <strong>ACE</strong>.<br />
— Sends the packet back down to its own microblock using the Resource<br />
Manager.<br />
78 Writing Micro<strong>ACE</strong>s<br />
Revision 3.3, August 2001
Chapter 7<br />
Interface <strong>ACE</strong>s<br />
This chapter describes the interface <strong>ACE</strong>s, system-defined micro<strong>ACE</strong>s that every<br />
application uses to receive and transmit packets for each network interface port. The<br />
chapter contains the following sections:<br />
l “Overview” on page 79<br />
l “Initializing Interface <strong>ACE</strong>s” on page 81<br />
l “The Input <strong>ACE</strong>” on page 83<br />
l “The Output <strong>ACE</strong>” on page 85<br />
Overview<br />
Interface <strong>ACE</strong>s are micro<strong>ACE</strong>s whose microblocks allows the microengines in the<br />
IXP1200 to communicate with the network interface ports. An IXP1200-based system<br />
must include the interface <strong>ACE</strong>s in order for the <strong>IXA</strong> application to receive and<br />
transmit traffic through any port. The interface <strong>ACE</strong>s can be configured to handle<br />
both 10/100BaseT Ethernet and gigabit Ethernet ports.<br />
The purpose <strong>of</strong> interface <strong>ACE</strong>s is to mask network interface details that are specific<br />
to particular hardware environments. These objects act as packet sources and destinations,<br />
and as drivers for the network interfaces. They are opaque to other <strong>ACE</strong>s.<br />
You can configure interface <strong>ACE</strong>s using their exported crosscall interfaces, but you<br />
cannot modify them.<br />
There are two types <strong>of</strong> interface <strong>ACE</strong>, input and output.<br />
l<br />
The input interface <strong>ACE</strong>, named by convention ifaceInput, is responsible for<br />
receiving packets from all <strong>of</strong> the physical ports. An input <strong>ACE</strong> contains a source<br />
microblock, which acts as a source <strong>of</strong> packet buffers for its microblock group. The<br />
input <strong>ACE</strong> passes received packets to the next microblock in the group.<br />
Revision 3.3, August 2001<br />
Interface <strong>ACE</strong>s 79
Overview<br />
l<br />
The output interface <strong>ACE</strong>, named by convention ifaceOutput, is responsible<br />
for transmitting packets on all <strong>of</strong> the physical ports. An output <strong>ACE</strong><br />
contains a sink microblock, which consumes packet buffers for the microblock<br />
group. The output <strong>ACE</strong> can receive packets from the previous microblock<br />
in its own group or another group, or from a conventional <strong>ACE</strong>.<br />
An application must include the microcode portions <strong>of</strong> these <strong>ACE</strong>s with any<br />
microcode <strong>of</strong> its own to create the microcode image that it downloads to each<br />
<strong>of</strong> the microengines as part <strong>of</strong> its initialization and startup procedure.<br />
l<br />
l<br />
To initialize an application, you run a startup script that loads, configures,<br />
and starts an input and output <strong>ACE</strong> for each port on which the application<br />
will receive and transmit packets.<br />
You combine the microblocks for the interface <strong>ACE</strong>s with any microblocks<br />
<strong>of</strong> your own to create the microcode image that you download to each <strong>of</strong> the<br />
microengines as part <strong>of</strong> the initialization and startup procedure.<br />
The core component <strong>of</strong> an interface <strong>ACE</strong> is written in C/C++. When your application<br />
creates an interface <strong>ACE</strong> during system initialization, the <strong>ACE</strong>’s initialization<br />
function instantiates the ingress or egress class and required helper<br />
classes. Depending on the IXP1200-based board configuration, the initialization<br />
procedure instantiates helper classes as needed for the proper types <strong>of</strong> network<br />
interface ports.<br />
Interface <strong>ACE</strong><br />
Crosscalls<br />
At runtime, an application can configure both physical and logical aspects <strong>of</strong> an<br />
input port using the crosscall interfaces exported by the input <strong>ACE</strong>. The input<br />
<strong>ACE</strong> exports two interfaces:<br />
l<br />
l<br />
The portMgmt interface defines operations that allow an application to<br />
control the physical configuration <strong>of</strong> a port. The physical properties <strong>of</strong> a port<br />
include such things as its port number, MAC address, and whether it is<br />
enabled.<br />
The logicalIfMgmt interface defines operations that allow an application<br />
to control the logical configuration <strong>of</strong> a port. An application can define<br />
multiple logical interface configurations for each port and treat each logical<br />
interface as a virtual port. This allows the application to associate multiple<br />
IP addresses with one physical port.<br />
Only the input <strong>ACE</strong> defines <strong>IXA</strong> IDL crosscall interfaces; it is not necessary to<br />
configure output <strong>ACE</strong>s after installation. To invoke these crosscalls, a program<br />
or <strong>ACE</strong> must connect to the server and initialize the client side <strong>of</strong> each interface<br />
before making any calls. The initialization routine <strong>of</strong> the input <strong>ACE</strong> initializes<br />
the server side <strong>of</strong> its crosscall interfaces.<br />
80 Interface <strong>ACE</strong>s<br />
Revision 3.3, August 2001
Initializing Interface <strong>ACE</strong>s<br />
A complete reference for the input <strong>ACE</strong> configuration crosscalls is provided in the<br />
<strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Source Code<br />
Location<br />
The source code for the interface <strong>ACE</strong>s, including the <strong>IXA</strong> IDL and generated stub<br />
files for the input <strong>ACE</strong> crosscalls, can be found in the following location:<br />
<strong>SDK</strong>installpath/src/microace/aces/interface_ace<br />
Initializing Interface <strong>ACE</strong>s<br />
When you initialize the IXP1200 system, using a management program or startup<br />
script, you specify which ports to use and provide the microcode images for each<br />
microengine. To use the interface <strong>ACE</strong>s, you must build their microblocks into at least<br />
one input and one output microcode image.<br />
After configuring the microengines, the management program or startup script starts<br />
and binds the interface <strong>ACE</strong>s, along with any other micro<strong>ACE</strong>s and conventional<br />
<strong>ACE</strong>s in the application.<br />
Creating a<br />
Microcode<br />
Image with an<br />
Interface <strong>ACE</strong><br />
Microblock<br />
Each microengine is configured for a microcode type, that determines whether it will<br />
perform input or output operations, and on which type <strong>of</strong> port. When you build a<br />
microcode image that includes the microblock for an input or output <strong>ACE</strong>, that<br />
microblock determines the type <strong>of</strong> the image. The type <strong>of</strong> a microcode image is determined<br />
as shown in the following table:<br />
Type<br />
Slow ingress<br />
Slow egress<br />
Fast ingress<br />
Fast egress<br />
Other<br />
Description<br />
The image contains the microblock for the input interface <strong>ACE</strong>, configured<br />
for 10/100BaseT ports.<br />
The image contains the microblock for the output interface <strong>ACE</strong>, configured<br />
for 10/100BaseT ports.<br />
The image contains the microblock for the input interface <strong>ACE</strong>, configured<br />
for gigabit ports.<br />
The image contains the microblock for the output interface <strong>ACE</strong>, configured<br />
for gigabit ports.<br />
The image does not contain an interface <strong>ACE</strong> microblock.<br />
When you specify the microcode images, either programmatically using the RmUeng-<br />
SetUcode function or in the system configuration file, using the file keyword, you<br />
specify the type. The Resource Manager than assigns each microcode image to a<br />
microengine with the correct type.<br />
Interface <strong>ACE</strong>s 81<br />
Revision 3.3, August 2001
Initializing Interface <strong>ACE</strong>s<br />
When you allow the Resource Manager to configure the microengines (by using the<br />
startup script or the Resource Manager function RmSetPortConfig), it sets the types<br />
automatically. You can see how the types are assigned using the Resource Manager<br />
function RmUengGetConfig. To specifically configure a microengine with a type, use<br />
the Resource Manager function RmUengSetConfig.<br />
Starting,<br />
Naming, and<br />
Binding<br />
Interface <strong>ACE</strong>s<br />
You can create, start, and bind interface <strong>ACE</strong>s programmatically, using Resource<br />
Manager functions in a management program, or you can use the startup scripts and<br />
system configuration file for the IXDP1200 Advanced Development Platform. See<br />
Chapter 4, “Configuring and Starting <strong>IXA</strong> Systems.”<br />
You can specify any <strong>ACE</strong> name for an interface <strong>ACE</strong>, but they are, by convention and<br />
by default, named ifaceInput and ifaceOutput. The interface <strong>ACE</strong>s reside at the<br />
root level <strong>of</strong> the Name Server’s name space. To refer to them and their targets, use<br />
names in the form:<br />
/ifaceInput/target_name<br />
Because it is a micro<strong>ACE</strong>, the input <strong>ACE</strong>’s default target must be statically bound<br />
to the micro<strong>ACE</strong> containing the next microblock in the processing pipeline. You can<br />
create a static binding in either <strong>of</strong> the following ways:<br />
l<br />
l<br />
Programmatically, use the Resource Manager function RmBindMicroAce, rather<br />
than the Resolver function ix_res_bind. For example:<br />
RmBindMicroAce ("/ifaceInput/default", "/MyAce");<br />
In the configuration file for the startup script, use the static flag for the bind<br />
statement. For example:<br />
bind static ifaceInput/default MyAce<br />
For example, suppose the application contains a micro<strong>ACE</strong> named MyAce, and the<br />
microcode puts the microblock for My<strong>ACE</strong> next in the processing pipeline after the<br />
input <strong>ACE</strong>. Use the following code to create the static bindings:<br />
RmBindMicroAce ("/MyAce/default"); "/ifaceOutput");<br />
RmBindMicroAce ("/ifaceInput/default", "/MyAce");<br />
An output <strong>ACE</strong> can receive packets from a previous microblock in the same group,<br />
from another microblock group, or from another <strong>ACE</strong>. Any <strong>ACE</strong> that needs to<br />
transmit packets must create a target for transmission and bind it to the output <strong>ACE</strong>.<br />
For example, suppose the core component <strong>of</strong> MyAce receives packets from another<br />
<strong>ACE</strong>, and defines a target, Tx, with which to transmit them. Use the following code<br />
to create a dynamic binding between the Tx target <strong>of</strong> MyAce and the output <strong>ACE</strong>:<br />
ix_res_bind ("/MyAce/Tx", "/ifaceOutput");<br />
To create this dynamic binding in the configuration file, use the bind statement as<br />
follows:<br />
bind dynamic MyAce/Tx ifaceOutput<br />
82 Interface <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The Input <strong>ACE</strong><br />
The Input <strong>ACE</strong><br />
The input <strong>ACE</strong> can be configured to receive packets from either the 10/100BaseT<br />
Ethernet or the gigabit Ethernet ports. The input <strong>ACE</strong> is implemented as a micro<strong>ACE</strong>.<br />
The core component is written in C++.<br />
The microblock handles packet flow by getting packets from the port, and passing<br />
them to the next microblock in its group. It never sends packets up to its core component.<br />
The input <strong>ACE</strong> does not define any targets other than the default target, which<br />
you must bind statically to the micro<strong>ACE</strong> containing the next microblock in the<br />
group. You do not normally bind the targets <strong>of</strong> other <strong>ACE</strong>s to the input <strong>ACE</strong>.<br />
The input <strong>ACE</strong> core component manages the physical and logical configurations for<br />
each port, and keeps statistics on traffic flow. It acts as a server for the exported<br />
configuration crosscalls.<br />
Configuring<br />
Interface <strong>ACE</strong>s<br />
Using<br />
Crosscalls<br />
Only the input <strong>ACE</strong> defines an <strong>IXA</strong> IDL crosscall interface, as it is not necessary to<br />
configure the output <strong>ACE</strong> after installation. Applications can invoke the input <strong>ACE</strong><br />
crosscalls to do the following:<br />
l<br />
l<br />
l<br />
l<br />
Set physical port properties such as MAC address<br />
Set logical interface properties such as a list <strong>of</strong> IP addresses<br />
Enable or disable a network interface port<br />
Retrieve various interface statistics such as the number <strong>of</strong> bytes sent or received<br />
The crosscalls operations are defined in two interfaces, the portMgmt interface and<br />
the logicalIfMgmt interface. The input <strong>ACE</strong> acts as a server for crosscalls and<br />
executes crosscalls on a per-port basis. The initialization routine <strong>of</strong> the input <strong>ACE</strong><br />
initializes the server side <strong>of</strong> both interfaces.<br />
To invoke these crosscalls, a program or <strong>ACE</strong> must initialize the client side <strong>of</strong> the<br />
interfaces before making any calls to the crosscall reference stub functions. A<br />
complete reference for the exported crosscalls is provided in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
When you generate the input <strong>ACE</strong> configuration crosscall C files from the provided<br />
interface definition file, ingress_ace.idl, the <strong>IXA</strong> IDL compiler produces the<br />
following files that you must link into the call client:<br />
Generated File<br />
ingress_ace_stub.c<br />
ingress_ace_stub.h<br />
ingress_ace_cb.c<br />
ingress_ace_cb.h<br />
Description<br />
Contains the stub functions for crosscall references<br />
and the client-side interface initialization and termination<br />
functions.<br />
Contains the templates for deferred operation callback<br />
functions, and the callback function vector table. Use<br />
the templates to implement handler functions for<br />
returned values, and modify the vector table to point to<br />
the function implementations.<br />
Interface <strong>ACE</strong>s 83<br />
Revision 3.3, August 2001
The Input <strong>ACE</strong><br />
Responding to<br />
Input <strong>ACE</strong><br />
Configuration<br />
Crosscalls<br />
Input <strong>ACE</strong> configuration crosscalls that retrieve values are defined as deferred operations.<br />
To handle the values that are returned asynchronously from these calls, the<br />
client program or <strong>ACE</strong> must define handler callback functions.<br />
For each deferred operation, the <strong>IXA</strong> IDL compiler generates a function template for<br />
the callback function in the ingress_ace_cb.c file. The crosscall client must implement<br />
a callback function based on the template. It must then modify the callback<br />
function vector table in the ingress_ace_cb.c file to point to the implementation<br />
rather than the template function.<br />
The following code fragment shows an example <strong>of</strong> how to change the callback function<br />
vectors.<br />
ix_base_t baseArray[0]; /* for IDL interface */<br />
ix_error err;<br />
ix_ace *pAce = (ix_ace *)pIng; /* our global variable */<br />
CC_VMT_portMgmt* pVmtPort = 0;<br />
err = sk_portMgmt_init (&baseArray[0],&pAce->cap[0]);<br />
if (err)<br />
IGA_ERROR_CHAIN(err, sk_portMgmt_init);<br />
err = getCCVMT_portMgmt(&baseArray[0], &pVmtPort);<br />
if (err)<br />
IGA_ERROR_CHAIN(err, getCCVMT_portMgmt);<br />
/* Fill in pointers to implementation <strong>of</strong> functions */<br />
pVmtPort->_pCC_portMgmt_portGetPorts = portGetPorts;<br />
pVmtPort->_pCC_portMgmt_portGetConfig = portGetConfig;<br />
pVmtPort->_pCC_portMgmt_portSetConfig = portSetConfig;<br />
pVmtPort->_pCC_portMgmt_portEnable = portEnable;<br />
pVmtPort->_pCC_portMgmt_portDisable = portDisable;<br />
pVmtPort->_pCC_portMgmt_portGetFlags = portGetFlags;<br />
pVmtPort->_pCC_portMgmt_portSetFlags = portSetFlags;<br />
pVmtPort->_pCC_portMgmt_portAddMacAddrFilter =<br />
portAddMacAddrFilter;<br />
pVmtPort->_pCC_portMgmt_portRemoveMacAddrFilter =<br />
portRemoveMacAddrFilter;<br />
pVmtPort->_pCC_portMgmt_portGetMacAddr = portGetMacAddr;<br />
pVmtPort->_pCC_portMgmt_portSetMacAddr = portSetMacAddr;<br />
pVmtPort->_pCC_portMgmt_portSetPromiscMode = portSetPromiscMode;<br />
pVmtPort->_pCC_portMgmt_portClearPromiscMode =<br />
portClearPromiscMode;<br />
pVmtPort->_pCC_portMgmt_portClearStats = portClearStats;<br />
pVmtPort->_pCC_portMgmt_portGetSnmpStats = portGetSnmpStats;<br />
DBG_MSG("ingressAceIdlInit : portMgmt init successful.\n");<br />
Managing<br />
Physical Ports<br />
The operations defined in the portMgmt interface manage the physical port configuration<br />
<strong>of</strong> an IXP 1200 system. An application can use these crosscalls to do the<br />
following:<br />
84 Interface <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The Output <strong>ACE</strong><br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Initialize and configure the 10/100BaseT ports under the 21440 Octal MAC, and<br />
gigabit ports under the IXF1004.<br />
Enable and disable ports for reception (Rx).<br />
Add and remove MAC addresses for address filtering on a port.<br />
Turn promiscuous mode on or <strong>of</strong>f for a port.<br />
Gather SNMP/RMON statistics for a port, and clear statistics.<br />
Store configuration information, including port type (slow or fast), MTU, MAC<br />
address, and port status flags, for retrieval by applications.<br />
Managing<br />
Logical Port<br />
Configuration<br />
The operations defined in the logicalIfMgmt interface manage the logical, or<br />
virtual, port configuration <strong>of</strong> an IXP 1200 system You can define multiple logical<br />
interfaces for a port. An application can use these crosscalls to do the following:<br />
l<br />
Create, maintain, and destroy logical interface properties for a port. Properties<br />
include:<br />
— IPv4 address<br />
— Mask<br />
— Interface number<br />
— Interface name<br />
— Status flags.<br />
l<br />
Store the logical interface information for retrieval by applications.<br />
The Output <strong>ACE</strong><br />
The output <strong>ACE</strong> can be configured to transmit packets on either the 10/100BaseT or<br />
the gigabit Ethernet ports in an IXP1200 system.<br />
The output <strong>ACE</strong> is a micro<strong>ACE</strong>, whose core component is implemented in C++. It<br />
manages the physical properties <strong>of</strong> a network interface port, and its own microblock.<br />
It does not manage the logical interface properties. The output <strong>ACE</strong> does not require<br />
run-time configuration, and does not export any crosscalls.<br />
Other <strong>ACE</strong>s can bind targets to an output <strong>ACE</strong> and send packets to it. The output<br />
<strong>ACE</strong> relays these packets to the microcode block for transmission.<br />
To manage the physical port properties, the output <strong>ACE</strong> defines an internal method<br />
API to do the following:<br />
l<br />
l<br />
Initialize and configure the 10/100BaseT ports under the 21440 Octal Mac, and<br />
fast ports under the IXF1004.<br />
Enable ports for transmission.<br />
The output <strong>ACE</strong> is always paired with a corresponding microcode block for an input<br />
<strong>ACE</strong> that receives packets on the same port, although the input microcode block need<br />
not be in the same group.<br />
Interface <strong>ACE</strong>s 85<br />
Revision 3.3, August 2001
The Output <strong>ACE</strong><br />
Sample Output<br />
Configurations<br />
There are many possible combinations <strong>of</strong> modes, starting ports, and starting FIFOs<br />
for the output microblocks. This section outlines some <strong>of</strong> the possible configurations<br />
that would work best on an IXP1200 Evaluation Platform, and provides some sample<br />
setup code for them.<br />
The following table lists some suggested configurations <strong>of</strong> one or more output<br />
microblocks for particular setups.<br />
Supported<br />
Ports<br />
Output<br />
Microblock<br />
Mode Start Port Start FIFO<br />
8 100Mb SlowEgress 16 TFIFO entry 0 0<br />
8 100 Mb 1<br />
1Gb<br />
SlowEgress 8 TFIFO entry 0 0<br />
FastEgress 8 TFIFO entry 8 1<br />
2 1Gb FastEgress 8 TFIFO entry 8 0<br />
FastEgress 8 TFIFO entry 9 1<br />
16 100 Mb SlowEgress 8 TFIFO entry 0 0<br />
SlowEgress 8 TFIFO entry 8 1<br />
86 Interface <strong>ACE</strong>s<br />
Revision 3.3, August 2001
Chapter 8<br />
Stack and Library <strong>ACE</strong>s<br />
This chapter describes system-defined <strong>ACE</strong>s provided with the <strong>SDK</strong> for specific<br />
purposes, such as communicating with the operating system’s TCP/IP stack and<br />
performing layer-three unicast packet forwarding. The chapter contains the<br />
following sections:<br />
l “Overview” on page 87<br />
l “The Stack <strong>ACE</strong>” on page 88<br />
l “The L3 Forwarder Library <strong>ACE</strong>” on page 89<br />
l “The L2 Bridging Library <strong>ACE</strong>” on page 91<br />
l “The NAT Library <strong>ACE</strong>s” on page 94<br />
Overview<br />
The <strong>IXA</strong> <strong>SDK</strong> provides the stack <strong>ACE</strong> to represent the Linux * TCP/IP stack, and<br />
library <strong>ACE</strong>s to perform typical networking tasks such as packet forwarding.<br />
The stack <strong>ACE</strong> is a conventional <strong>ACE</strong>. To send packets to the stack you bind <strong>ACE</strong><br />
targets to the stack <strong>ACE</strong>, and to receive packets from the stack you bind its target to<br />
an application or output <strong>ACE</strong>.<br />
Library <strong>ACE</strong>s are generally (but not always) implemented as micro<strong>ACE</strong>s. To integrate<br />
library micro<strong>ACE</strong>s into your application, you link and compile the microblocks<br />
with the microblocks <strong>of</strong> interface and application-specific micro<strong>ACE</strong>s. For more<br />
information on micro<strong>ACE</strong> architecture, see Chapter 6, “Writing Micro<strong>ACE</strong>s,” and<br />
Chapter 6, “Micro<strong>ACE</strong> Support Services,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
You load and bind stack and library <strong>ACE</strong>s as part <strong>of</strong> system initialization. The distribution<br />
includes scripts for loading and starting the supplied <strong>ACE</strong>s. You modify the<br />
startup script’s configuration file to load and start the proper system and library<br />
<strong>ACE</strong>s for your application.<br />
Revision 3.3, August 2001<br />
Stack and Library <strong>ACE</strong>s 87
The Stack <strong>ACE</strong><br />
Sample applications that use the library <strong>ACE</strong>s in various configurations can be found<br />
in the following location:<br />
<strong>SDK</strong>installpath/src/microace/apps<br />
The Stack <strong>ACE</strong><br />
The stack <strong>ACE</strong> is a system-defined <strong>ACE</strong> that integrates Linux TCP/IP stack with an<br />
<strong>IXA</strong> application.<br />
The stack <strong>ACE</strong> is implemented as a conventional <strong>ACE</strong> combined with a kernel-mode<br />
Ethernet device driver. The stack <strong>ACE</strong> appears to the Linux kernel as an Ethernet<br />
device, and to the <strong>IXA</strong> system as an <strong>ACE</strong>.<br />
The stack <strong>ACE</strong> does not perform any classification. When it receives a packets<br />
received from any <strong>ACE</strong> bound to it, the stack <strong>ACE</strong> directs that packet to the Linux<br />
TCP/IP stack.<br />
The stack <strong>ACE</strong> contains one target, named tx. Any packet received from the TCP/IP<br />
stack is directed to the <strong>ACE</strong> bound to that target. The following example shows the<br />
stack <strong>ACE</strong> bound directly to a network interface in both directions:<br />
TCP/IP stack<br />
stack <strong>ACE</strong><br />
tx Target<br />
default target bound to stack <strong>ACE</strong><br />
tx target bound to output <strong>ACE</strong><br />
input port<br />
input <strong>ACE</strong><br />
output <strong>ACE</strong><br />
output port<br />
Starting and<br />
Configuring<br />
the Stack <strong>ACE</strong><br />
The stack <strong>ACE</strong> is, by convention, named stackAce, but you can give it any name. The<br />
stack <strong>ACE</strong> target is named /stack_<strong>ACE</strong>_name/tx. The source code and <strong>ACE</strong> executable<br />
file can be found in the following location:<br />
<strong>SDK</strong>installpath/src/microace/aces/kstack<br />
You can start and bind the stack <strong>ACE</strong> using OMS calls in a manager program. For<br />
example, use the following code to bind the target <strong>of</strong> the stack <strong>ACE</strong> to the output<br />
interface <strong>ACE</strong>, and the application-defined ARP target <strong>of</strong> MyAce to the stack <strong>ACE</strong>:<br />
ix_res_bind ("/stackAce/tx", "/ifaceOutput");<br />
ix_res_bind ("/MyAce/ARP", "/stackAce");<br />
88 Stack and Library <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The L3 Forwarder Library <strong>ACE</strong><br />
You can also start and bind the stack <strong>ACE</strong> using the startup and configuration scripts.<br />
In the ixsys.config file:<br />
l<br />
l<br />
l<br />
Use the ace keyword to start the stack <strong>ACE</strong>.<br />
Create dynamic bindings for it using the bind keyword.<br />
Use the sh keyword to run the stackconfig configuration utility.<br />
This utility uses the port configuration specified in the ixsys.config file. You do not<br />
need to specify further configuration details. For example, the following statement<br />
launches the stackconfig configuration utility, specifying the name <strong>of</strong> the stack<br />
<strong>ACE</strong> as stackAce, and giving the location and name <strong>of</strong> the system configuration file:<br />
sh ./stackconfig stackAce ./ixsys.config<br />
For examples <strong>of</strong> using the startup utilities and configuration files, see Chapter 4,<br />
“Configuring and Starting <strong>IXA</strong> Systems.”<br />
The L3 Forwarder Library <strong>ACE</strong><br />
The <strong>IXA</strong> <strong>SDK</strong> includes a library <strong>ACE</strong> that performs layer-three forwarding, which<br />
you can include in routing applications. The library <strong>ACE</strong> is implemented as a<br />
micro<strong>ACE</strong>.<br />
The L3 forwarder micro<strong>ACE</strong> is an IP version 4 unicast forwarder. It takes in IP<br />
packets from one network interface port, decides what their destinations are, and<br />
sends them out through another port based on the decision. It makes the routing decision<br />
and forwards the IP packet according to the standard described by the Internet<br />
Engineering Task Force (IETF) RFC 1812. The L3 forwarder <strong>ACE</strong> conforms to this<br />
standard in the following area:<br />
l<br />
l<br />
l<br />
l<br />
Verifying that an IP packet is valid (checksums, bad source and destination<br />
addresses, options, and so on),<br />
Updating the various fields (Time to Live (TTL), options),<br />
Performing the destination lookup<br />
Dealing with errors (typically through the Internet Control Message Protocol<br />
ICMP).<br />
For more information on this standard, see www.ietf.org.<br />
The L3 forwarder micro<strong>ACE</strong> forwards IP packets based on a given routing table, and<br />
performs address resolution using the Ethernet Address Resolution Protocol (ARP).<br />
Like all micro<strong>ACE</strong>s, the forwarder contains a microblock and a core component:<br />
l<br />
l<br />
The microblock performs fast-path forwarding <strong>of</strong> IP version 4 packets. For exception<br />
packets, such as those requiring options processing, the microblock sends the<br />
packet to the core component.<br />
The core component is implemented in C++. In addition to processing exception<br />
packets, the core component generates ICMP error messages, handles all ARP<br />
messages and maintains the routing tables.<br />
Revision 3.3, August 2001<br />
Stack and Library <strong>ACE</strong>s 89
The L3 Forwarder Library <strong>ACE</strong><br />
Starting the<br />
Forwarder<br />
<strong>ACE</strong><br />
The forwarder library <strong>ACE</strong> is named by convention L3Fwdr, but you can give it any<br />
name when you launch it. To use the forwarder <strong>ACE</strong>, you typically configure the<br />
L3Fwdr microblock as the next block in each microblock group that contains an input<br />
<strong>ACE</strong> microblock, so that it accepts packets from the input <strong>ACE</strong>. If your application<br />
needs to do other processing on incoming packets first, you might need other <strong>ACE</strong>s<br />
between the input <strong>ACE</strong> and the forwarder.<br />
To start and initialize the L3 forwarder, use thel3config configuration utility. This<br />
utility uses the port configuration specified in the ixsys.config file, then adds<br />
routing table and ARP entries for the L3 forwarder library <strong>ACE</strong> according to specifications<br />
in the L3 forwarder configuration file. Launch this utility from<br />
theixsys.config file as a shell command.<br />
For example, the following statement launches the l3config configuration utility,<br />
specifying the name <strong>of</strong> the L3 forwarding library <strong>ACE</strong> as L3Fwdr, and giving the locations<br />
and names <strong>of</strong> both configuration files:<br />
sh ./l3config L2Bridge ./ixsys.config ./l3forwarder.config<br />
Binding the<br />
Targets<br />
The forwarder <strong>ACE</strong> defines two targets, /forwarder_name/out_if and<br />
/forwarder_name/stack. The forwarder directs packes as follows:<br />
l<br />
l<br />
It sends locally destined packets to stack target. These include broadcast, multicast,<br />
and unicast packets whose destination is one <strong>of</strong> the IP addresses assigned to<br />
the system.<br />
It sends all other valid, correctly routed packets to the out_if target.<br />
If no further processing is needed for outbound destinations, you can statically bind<br />
the out_if target directly to the output interface <strong>ACE</strong>, and configure the microcode<br />
processing pipeline in the same way. To do further processing on outbound packets,<br />
bind the out_if target to the next <strong>ACE</strong> in the processing pipeline. Dynamically bind<br />
the out_if target to the output <strong>ACE</strong> or other handler <strong>ACE</strong> so that the forwarder’s<br />
core component can also use it to transmit packets.<br />
Similarly, you can dynamically bind the stack target directly to the stack <strong>ACE</strong> so that<br />
the forwarder’s core component can pass packets with local destinations to the Linux<br />
TCP/IP stack. If your application needs to do further processing on locally destined<br />
packets, bind the stack target to another handler <strong>ACE</strong>.<br />
For an example <strong>of</strong> starting, configuring, and binding the forwarder <strong>ACE</strong>, see<br />
Chapter 3, “Compiling and Testing Applications.”<br />
Configuring<br />
the Forwarder<br />
The L3 forwarder configuration file uses keyword statements to set up the initial<br />
configuration <strong>of</strong> the routing table and ARP cache for the L3 forwarder library <strong>ACE</strong>.<br />
l<br />
The configuration keywords are described in detail in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
l For an example <strong>of</strong> using the startup utility and configuration file, see Chapter 4,<br />
“Configuring and Starting <strong>IXA</strong> Systems.”<br />
90 Stack and Library <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The L2 Bridging Library <strong>ACE</strong><br />
The L3 forwarding <strong>ACE</strong> exports a crosscall interface that your application uses to<br />
manipulate the routing table, ARP table, and otherwise configure the behavior at run<br />
time. The crosscall operations are organized into functional areas as follows:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Route table calls allow you to:<br />
— Add and delete route table entries<br />
— Perform route table lookups<br />
— Print the route table to a file for debugging<br />
Forwarding configuration calls allow you to get and set configuration flags to<br />
control forwarding behavior<br />
ARP table and configuration calls allow you to:<br />
— Add and delete ARP table entries<br />
— Perform ARP table lookups<br />
— Get and set the ARP sleep time, default age, and back<strong>of</strong>f values<br />
ICMP calls allow you to get and set the ICMP drain value, sleep time, and queue<br />
depth<br />
A statistics call allows you to get statistical information about forwarding activity<br />
for a particular network interface port.<br />
Interface calls allow you to:<br />
— Get and set the layer 2 MAC address <strong>of</strong> a port<br />
— Get and set layer 3 IP addresses <strong>of</strong> a port<br />
— Enable and disable ports<br />
— Get and set the MTU for a port<br />
The crosscalls are described in detail in the <strong>IXA</strong> <strong>SDK</strong> Reference. For more information<br />
on using crosscalls, see Chapter 11, “Communication Within an Application.”<br />
The L2 Bridging Library <strong>ACE</strong><br />
The L2 bridging library <strong>ACE</strong> implements a layer-two bridge according to the<br />
ISO/IEC 15802-3 standard, as described in the ANSI/IEEE Std 802.1D, 1998 Edition.<br />
It is implemented as a micro<strong>ACE</strong>. Like all micro<strong>ACE</strong>s, the forwarder <strong>ACE</strong> contains a<br />
microblock and a core component:<br />
l<br />
l<br />
The microblock performs fast-path forwarding <strong>of</strong> unicast IP version 4 packets<br />
between networks or network segments. It maintains an 8000-entry forwarding<br />
table, and a logical port state that determines how and whether it transmits<br />
packets on a port. It sends exception packets to the core component.<br />
The core component processes exception packets. It defines targets that the<br />
micro<strong>ACE</strong> uses to forward packets to the output interface <strong>ACE</strong> or to other <strong>ACE</strong>s,<br />
such as the stack <strong>ACE</strong> or L3 forwarding <strong>ACE</strong>.<br />
The core component administers the port states and the MAC forwarding table.<br />
It performs aging for dynamic (learned) table entries, and deletes them after the<br />
maximum aging time. It exports crosscalls that allow an application to configure<br />
the table and port states at run time. See “Configuring the L2 Bridger” on page 94.<br />
Stack and Library <strong>ACE</strong>s 91<br />
Revision 3.3, August 2001
The L2 Bridging Library <strong>ACE</strong><br />
Packet<br />
Processing<br />
The microblock drops any packet whose source address is <strong>of</strong> type multicast or broadcast,<br />
whose size exceeds port MTU or is less than 64 bytes (runts), or that has a<br />
reserved destination address.<br />
Packet handling depends on the logical port state:<br />
l When a port is disabled, any packet destined for the port is dropped.<br />
l When a port is blocked or listening and the incoming packet is a BPDU packet, it<br />
is sent to the core component. Otherwise it is dropped.<br />
l<br />
l<br />
When a port is learning, the microblock adds the source MAC address <strong>of</strong> an<br />
incoming packet to the forwarding table.<br />
When a port is forwarding, the microblock learns the MAC address and performs<br />
all packet forwarding. In this state, if the destination MAC address on received<br />
packet is equal to the MAC address <strong>of</strong> the port, this packet is meant for local<br />
administration, L3 forwarding, or a nonroutable protocol. The microblock queues<br />
the packet to a local target for handling.<br />
The core component performs a flooding operation for an incoming packet if the<br />
destination address is not found in the forwarding table. Flooding copies packets,<br />
and can be resource intensive. You can limit flooding to a subset <strong>of</strong> ports by assigning<br />
ethertype protocols to specific ports.<br />
The following exception conditions cause the microblock to send a packet to the core<br />
component:<br />
Condition<br />
BPDU<br />
Learn<br />
Learn and Forward<br />
Description<br />
The incoming port is in the blocked, listening, learning, or forwarding<br />
state and the destination address matches the BPDU multicast<br />
address.<br />
This occurs under either <strong>of</strong> the following conditions:<br />
l The receiving port is in learning state and the source MAC address<br />
was not found in the MAC forwarding table.<br />
l The receiving port is in forwarding state but the output port was not<br />
in the forwarding state, and the source MAC address was not found<br />
in the MAC forwarding table.<br />
The microblock adds an entry to the MAC forwarding table, providing<br />
the source MAC address, the ingress port number, and the dynamic<br />
entry type. An event handler in the core component ages the learned<br />
entries.<br />
The source MAC address is not found in the MAC forwarding table,<br />
the destination MAC address is found, and both the input and output<br />
ports are in forwarding state.<br />
The microblock adds the entry and the core component ages it, as for<br />
the Learn condition.<br />
92 Stack and Library <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The L2 Bridging Library <strong>ACE</strong><br />
Condition<br />
Learn and<br />
Flood<br />
Description<br />
Neither the source nor the destination addresses are found in the<br />
MAC forwarding table, and the input port is in forwarding state.<br />
This packet is flooded to ports that are configured for the protocol type<br />
found in the ethertype <strong>of</strong> this packet.<br />
Learn and ARP The destination MAC address is addressed to this port but the source<br />
MAC address is not found in the MAC forwarding table. The input port<br />
is in forwarding or learning state.<br />
The core component learns the address and passes the packet to<br />
either the L3 forwarder <strong>ACE</strong> or the stack <strong>ACE</strong>.<br />
Flood<br />
Destination MAC address is not found in the forwarding table but the<br />
source MAC address has found a match.<br />
When the input port is in forwarding state, the packet is flooded to<br />
ports that are configured for the protocol type found in the ethertype<br />
<strong>of</strong> this packet.<br />
When the input port is in learning or forwarding state, the microcode<br />
adds a MAC forwarding entry for a unicast, multicast, or broadcast<br />
packet.<br />
Starting the L2<br />
Bridger<br />
The L2 bridging library <strong>ACE</strong> is named by convention L2Bridge, but you can give it<br />
any name when you launch it. The source code, including the <strong>ACE</strong> executable file<br />
and microblock source, can be found in the following location:<br />
<strong>SDK</strong>installpath/src/microace/aces/l2bridge_ace<br />
To use the bridging <strong>ACE</strong>, you typically configure the L2Bridge microblock as the<br />
next block in each microblock group that contains an input <strong>ACE</strong> microblock, so that<br />
it accepts packets from the input <strong>ACE</strong>. If your application needs to do other<br />
processing on incoming packets first, you might need other <strong>ACE</strong>s between the input<br />
<strong>ACE</strong> and the bridger.<br />
The bridger <strong>ACE</strong> defines two targets, /bridger_name/out_if and<br />
/bridger_name/stack.<br />
To start and initialize the L2 bridger, use the l2config configuration utility. This<br />
utility uses the port configuration specified in the system configuration file, then<br />
adds route table entries and sets logical port properties specific to the L2 bridging<br />
library <strong>ACE</strong> according to specifications in the L2 bridge configuration file. Launch<br />
this utility from the ixsys.config file as a shell command.<br />
For example, the following statement launches the l2config configuration utility,<br />
specifying the name <strong>of</strong> the L2 bridging library <strong>ACE</strong> as L2Bridge, and giving the locations<br />
and names <strong>of</strong> both configuration files:<br />
sh ./l2config L2Bridge ./ixsys.config ./l2bridge.config<br />
Stack and Library <strong>ACE</strong>s 93<br />
Revision 3.3, August 2001
The NAT Library <strong>ACE</strong>s<br />
Configuring<br />
the L2 Bridger<br />
The L2 bridge configuration file uses keyword statements to initialize the routes and<br />
port configuration needed by the L2 bridging <strong>ACE</strong>. All the commands operate at the<br />
layer-two level. The logical port configuration does not effect the physical behavior<br />
<strong>of</strong> the port.<br />
l<br />
The keywords are described in detail in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
l For an example <strong>of</strong> using the startup utility and configuration file, see Chapter 4,<br />
“Configuring and Starting <strong>IXA</strong> Systems.”<br />
The <strong>ACE</strong> exports a crosscall interface that your application uses to manipulate the<br />
routing table and port configuration at run time.<br />
You can use the crosscalls to:<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
l<br />
Enable and disable the collection <strong>of</strong> port activity statistics, in the form <strong>of</strong> RFC1493<br />
MIB attributes and tables, and retrieve the statistics.<br />
Update the MAC forwarding table, associating a destination port with destination<br />
MAC addresses and entry types (static or dynamic).<br />
Update the time that learned MAC forwarding table entries are allowed to age<br />
before being automatically removed.<br />
Update port states. A port state can be disabled, blocked, listening, learning, or<br />
forwarding.<br />
Enable and disable Ethernet bridging for a port.<br />
Enable and disable IP bridging for a port when routing is disabled for that port.<br />
Configure port groups for any ethertype protocol, to enable bridging for<br />
nonroutable protocols.<br />
The crosscalls are described in detail in the <strong>IXA</strong> <strong>SDK</strong> Reference. For more information<br />
on using crosscalls, see Chapter 11, “Communication Within an Application.”<br />
The NAT Library <strong>ACE</strong>s<br />
The NAT library application consists <strong>of</strong> two <strong>ACE</strong>s, the NAT micro<strong>ACE</strong> and the NAT<br />
controller, a conventional <strong>ACE</strong>. Together, these <strong>ACE</strong>s perform network address<br />
translation according to rules that you provide.<br />
Packet<br />
Processing<br />
The specific rules for network address translation are defined by your application in<br />
the NAT controller’s access control lists (ACLs). There are two types <strong>of</strong> ACL:<br />
l<br />
l<br />
A filter ACL contains filter rules that specify what actions to take on packets with<br />
specific destination addresses. The possible actions are pass, drop, and NAT.<br />
The NAT ACLs contains network address translation rules. When a packet<br />
matches a filter rule that specifies the NAT action, the <strong>ACE</strong> searches for a<br />
matching NAT rule in the NAT ACLs. The NAT controller maintains ACLs for the<br />
following types <strong>of</strong> network address translation:<br />
— Static<br />
— Dynamic<br />
94 Stack and Library <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The NAT Library <strong>ACE</strong>s<br />
— IP masquerade (port translation)<br />
— Virtual server (load balancing)<br />
The NAT micro<strong>ACE</strong> maintains a cache <strong>of</strong> translations, which it receives from the<br />
NAT controller. The microblock receives incoming packets, parses the header, and<br />
looks for a translation in its cache. If it finds one, it performs the specified IP address<br />
translation and forward the packet to the next microblock in its group.<br />
If the microblock finds no translation in the local cache, it flags an exception and<br />
sends the packet to the core component. The core component sends all packets it<br />
receives (from its own microblock or from other <strong>ACE</strong>s) to the NAT controller.<br />
The NAT controller searches its filter rules to determine whether network address<br />
translation should be performed for the packet. If it should, the <strong>ACE</strong> searches the<br />
appropriate NAT rules to find the correct translation.<br />
When it has found a suitable translation, the NAT controller passes both the translation<br />
and the packet back to the micro<strong>ACE</strong>. The micro<strong>ACE</strong> core component updates<br />
the translation cache, then passes the packet back to the microblock for processing.<br />
Special<br />
Handling<br />
By default, the NAT <strong>ACE</strong>s also handles the following special-case packet types:<br />
l FTP packets<br />
l TCP fragments<br />
l ICMP error packets<br />
You can choose to disable any <strong>of</strong> these provided handlers and replace them with your<br />
own handlers. To do this:<br />
1. Use the enableApps crosscall to disable the handler for a packet type. (For more<br />
information, see the <strong>IXA</strong> <strong>SDK</strong> Reference.)<br />
2. Provide your own handler <strong>ACE</strong> for the packet type.<br />
3. Bind the ALG target <strong>of</strong> the NAT micro<strong>ACE</strong> to your handler <strong>ACE</strong>.<br />
The following sections briefly describe how the NAT <strong>ACE</strong>s handle each special case.<br />
FTP Packet Handling<br />
An FTP PORT or PASV reply command embeds the IP address and port numbers in<br />
the payload. To perform address translation for a PORT or PASV reply command, the<br />
FTP handler parses the payload to find the embedded IP address and port number.<br />
l<br />
l<br />
If the embedded IP address is the same as the IP address in the IP header that<br />
requires translation, then the handler translates the embedded address also.<br />
For IP masquerading (port translation), the handler translates the embedded port<br />
number, assigning a port from the <strong>ACE</strong>’s pool.<br />
Stack and Library <strong>ACE</strong>s 95<br />
Revision 3.3, August 2001
The NAT Library <strong>ACE</strong>s<br />
When the handler modifies the embedded IP address or port, it also changes the<br />
number <strong>of</strong> bytes in the payload and saves the number in the other_data field <strong>of</strong> the<br />
FLOW_DATA structure in SDRAM. This causes a change in the sequence number or<br />
acknowledgement number for subsequent packets. The handler recalculates the IP<br />
checksum to reflect the data changes.<br />
TCP Fragment Handling<br />
When the NAT micro<strong>ACE</strong> receives fragments, it assumes that all <strong>of</strong> the header fields<br />
are in the first fragment. Upon receiving the first fragment, the fragment handler<br />
performs the NAT table lookup.<br />
l<br />
l<br />
If no entry is found, the micro<strong>ACE</strong> flags an exception and sends the packet buffer<br />
to the control <strong>ACE</strong>.<br />
If an entry is found, it begins collecting the fragments in a buffer. If all fragments<br />
are not received within the specified timeout period, the buffer is cleared. When<br />
the datagram is complete, the micro<strong>ACE</strong> begins address translation on the fragments.<br />
If it is a TCP or UDP packet the fragment handler performs address translation for<br />
both the TCP/UDP header and the IP header in the first fragment. For the<br />
remaining fragments, it translates only the IP header addresses. The handler<br />
recalculates all checksums to reflect the data changes.<br />
ICMP Error Packet Handling<br />
When the NAT micro<strong>ACE</strong> receives an ICMP packet, the ICMP handler checks that it<br />
is an ERROR packet, which contains an embedded IP header for the packet that<br />
caused the error. The ICMP handler performs address translation for the IP header<br />
embedded in the message, and recalculates the checksums accordingly. It modifies<br />
the following:<br />
l<br />
l<br />
l<br />
The IP addresses and checksum <strong>of</strong> the IP header embedded in the data <strong>of</strong> the<br />
ICMP packet.<br />
The ICMP header checksum.<br />
The normal IP header checksum.<br />
If the ICMP packet is not an ERROR message, the handler sends it to the default<br />
target. The handler does not store any state for ICMP packets.<br />
Starting the<br />
NAT <strong>ACE</strong>s<br />
To use the NAT library <strong>ACE</strong>s, you must start both the NAT micro<strong>ACE</strong> and the NAT<br />
controller <strong>ACE</strong>.<br />
l<br />
The NAT micro<strong>ACE</strong> is named by convention nat, but you can give it any name<br />
when you launch it. To start the micro<strong>ACE</strong>, you can use the microace keyword in<br />
the system configuration file. For example:<br />
microace nat ./Nat none 0 5 natc 3<br />
l<br />
The NAT controller is named by convention natc, but you can give it any name<br />
when you launch it. To start the NAT controller, you can use the ace keyword in<br />
the system configuration file. For example:<br />
96 Stack and Library <strong>ACE</strong>s<br />
Revision 3.3, August 2001
The NAT Library <strong>ACE</strong>s<br />
ace natc ./natctlr none 2 nat 1<br />
The source code, including the <strong>ACE</strong> executable files and microblock sources, can be<br />
found in the following locations:<br />
<strong>SDK</strong>installpath/src/microace/aces/nat_ace<br />
<strong>SDK</strong>installpath/src/microace/aces/nat_ctlr<br />
You can configure the microblock to get packets directly from the input interface <strong>ACE</strong><br />
microblock, or from the microblock <strong>of</strong> another processing <strong>ACE</strong> such as the L3<br />
forwarder. It can transmit packets directly to an output <strong>ACE</strong>, or to another micro<strong>ACE</strong><br />
for further processing.<br />
To initialize the NAT controller, use the natconfig configuration utility. This utility<br />
sets up the initial ACLs and rules according to specifications in the NAT configuration<br />
file that you supply. Launch this utility from the ixsys.config file as a shell<br />
command.<br />
For example, the following statement launches the natconfig configuration utility,<br />
specifying the name <strong>of</strong> the NAT controller <strong>ACE</strong> as natc, and specifying the configuration<br />
file as nat.config in the same directory:<br />
sh ./natconfig natc ./nat.config<br />
Binding the<br />
Targets<br />
The NAT micro<strong>ACE</strong> defines the following targets:<br />
Target<br />
Description<br />
PASS<br />
CONFIG<br />
DROP<br />
Bind this target statically to the micro<strong>ACE</strong> containing the next microblock<br />
in the group, as defined by the dispatch loop.<br />
When the micro<strong>ACE</strong> finds a cached translation for an incoming<br />
packet, it performs address translation as required then sends the<br />
packet to this target to continue normal processing.<br />
Bind this target to the NAT controller <strong>ACE</strong>.<br />
When the micro<strong>ACE</strong> finds no cached translation for an incoming<br />
packet, it sends the packet to this target so that the NAT controller<br />
can provide a new translation.<br />
This target must remain unbound.<br />
The micro<strong>ACE</strong> drops packets by sending them to this target. The<br />
packet buffer is automatically freed when passed to an unbound target.<br />
Stack and Library <strong>ACE</strong>s 97<br />
Revision 3.3, August 2001
The NAT Library <strong>ACE</strong>s<br />
Target<br />
ALG<br />
DEFAULT<br />
Description<br />
Bind as required for your application.<br />
When one <strong>of</strong> the special packet-handling features (for FTP, TCP fragments,<br />
or ICMP errors) is disabled, the micro<strong>ACE</strong> sends packets <strong>of</strong><br />
that type to this target.<br />
You can define rules to send packets to this target for applicationdefined<br />
handling. (ALG stands for application-level gateway.)<br />
Bind as required for your application.<br />
The micro<strong>ACE</strong> passes all non-TCP/UDP packets (except ARP packets)<br />
to this target.<br />
Configuring<br />
the NAT library<br />
<strong>ACE</strong>s<br />
The NAT controller <strong>ACE</strong> maintains a data structure containing access control lists<br />
(ACLs) which in turn contain the application-defined rules.<br />
l<br />
l<br />
The ACLs are created and initialized by the natconfig startup utility according<br />
to the information you provide in the NAT configuration file.<br />
The NAT controller exports a crosscall interface. Use these crosscalls to add and<br />
delete ACLs and rules at run time.<br />
When adding a rule, you can specify the rule’s position in its ACL. When searching<br />
the rules, the NAT controller applies the first matching rule to an incoming packet.<br />
l<br />
l<br />
l<br />
For more information on startup and configuration, see Chapter 4, “Configuring<br />
and Starting <strong>IXA</strong> Systems.”<br />
For more information on using crosscalls, see Chapter 11, “Communication<br />
Within an Application.”<br />
For detailed information on the configuration file keywords and configuration<br />
crosscalls, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
98 Stack and Library <strong>ACE</strong>s<br />
Revision 3.3, August 2001
Chapter 9<br />
Classifying Packets Using NCL<br />
This chapter describes how an <strong>ACE</strong> classifies incoming packets using its classification<br />
code, which you write in Network Classification Language (NCL).<br />
This chapter contains the following topics:<br />
l “How <strong>ACE</strong>s Handle Packets” on page 99<br />
l “What’s in the NCL Rules File” on page 100<br />
l “Defining Protocols” on page 102<br />
l “Defining Rules” on page 101<br />
l “How Rules Are Evaluated” on page 103<br />
l “What Rules Do” on page 104<br />
How <strong>ACE</strong>s Handle Packets<br />
An <strong>ACE</strong> does three things with a packet:<br />
l Classifies it<br />
l Acts on it<br />
l Disposes <strong>of</strong> it<br />
Packets are received by the IXP1200 as network traffic flows through it. A packet<br />
arrives at an <strong>ACE</strong> from the source to which it is bound as a destination target, as<br />
described in Chapter 5, “Controlling Packet Flow.” The source <strong>of</strong> a packet could be,<br />
for example, either a network interface or another <strong>ACE</strong> earlier in the processing<br />
chain. The <strong>ACE</strong> classifies each incoming packet according to classification rules<br />
defined in the <strong>ACE</strong>’s NCL rules file.<br />
Revision 3.3, August 2001<br />
Classifying Packets Using NCL 99
What’s in the NCL Rules File<br />
As a result <strong>of</strong> the classification, NCL rules trigger action functions that are defined in<br />
the <strong>ACE</strong>’s action code. Action functions can act on packets by examining or retrieving<br />
their contents, or dispose <strong>of</strong> packets by sending them to targets. An action function<br />
can make a final disposition, ending the classification process for that packet, or it can<br />
tell the <strong>ACE</strong> to continue with the classification process and evaluate more rules.<br />
What’s in the NCL Rules File<br />
An <strong>ACE</strong> classifies incoming packets according to the protocol and predicate definitions<br />
in its NCL rules file. Based on the classification, rules trigger action functions<br />
defined in the <strong>ACE</strong>’s action code. The rules file and action file are compiled into a<br />
single object, which you associate with the <strong>ACE</strong> in the <strong>ACE</strong> initialization function<br />
you define.<br />
The NCL rules file has two general parts. In the first part, you define the protocols<br />
and predicates that are the basis <strong>of</strong> classification. In the second part, you define the<br />
rules, which trigger specific actions based on how a packet satisfies the predicates. In<br />
addition to these basic elements, you can define sets and searches in the NCL rules<br />
file.<br />
Classification<br />
Elements<br />
The basic classification elements you define in the NCL rules file are rules and protocols.<br />
l<br />
l<br />
A rule determines whether some statement is true for the current packet. If it is,<br />
the rule specifies an action to take. The action is a function that you defined in the<br />
action code that is part <strong>of</strong> the same <strong>ACE</strong> as the NCL rules file.<br />
A protocol definition describes a set <strong>of</strong> fields <strong>of</strong> particular lengths. A protocol is<br />
usually added on as a header to one or more other nested protocols. The definition<br />
states which other protocols can be nested, and where they start.<br />
For convenience, you can also define named predicates to use in the rules and<br />
protocol definitions. A predicate determines whether something is true <strong>of</strong> a current<br />
packet — for example, whether it conforms to a certain protocol, or whether a particular<br />
field has a particular value. Predicates are named Boolean expressions, which<br />
can contain other predicates and Boolean expressions. You can define predicates as<br />
part <strong>of</strong> a protocol definition or separately.<br />
Sets and<br />
Searches<br />
NCL and the Action Services Library (ASL) together support data tables called sets.<br />
Sets associate application-defined data with packets. You define named searches associated<br />
with a specific set, which determine whether the current packet has a matching<br />
element in the set, based on the values <strong>of</strong> specified fields.<br />
You define and name the sets and searches in the NCL rules file, then use the<br />
compiler to generate corresponding objects in the action code. The sets are implemented<br />
on initialization. You populate the sets with data through actions.<br />
Searchable sets define collections <strong>of</strong> packets which are associated with each other by<br />
virtue <strong>of</strong> their contents. A set member (element) matches packets with a specific<br />
combination <strong>of</strong> field values. If you want to form collections on structural criteria, such<br />
100 Classifying Packets Using NCL<br />
Revision 3.3, August 2001
Defining Rules<br />
as “the set <strong>of</strong> all packets with IP header lengths greater than twenty bytes,” use a classification<br />
predicate rather than a searchable set; see “Defining Protocols” on<br />
page 102.<br />
Sets are an efficient way to track a large number <strong>of</strong> classes <strong>of</strong> packets. They allow you<br />
to keep state information for all packets that have the same values in specific fields.<br />
For example, you can count the number <strong>of</strong> packets that flow between any two specific<br />
IP address pairs, or maintain state for each TCP stream.<br />
For more information on sets and searches, see Chapter 13, “Using Sets <strong>of</strong> Data to<br />
Classify Packets.”<br />
Defining Rules<br />
NCL rules determine what action to take, based on the classification. A rule consists<br />
<strong>of</strong> two parts:<br />
l<br />
l<br />
A predicate part<br />
The predicate part <strong>of</strong> a rule is a Boolean expression that describes the conditions<br />
a packet must meet to have the specified action performed on it.<br />
Predicates might include static comparisons <strong>of</strong> packet contents or comparisons<br />
against dynamically-created state.<br />
An action part<br />
The action part <strong>of</strong> a rule is the name <strong>of</strong> an action function to be executed when the<br />
predicate is true, along with any additional arguments the named function<br />
expects. The action function performs some action upon the incoming packet.<br />
The following example shows the parts <strong>of</strong> a rule:<br />
rule allpackets { ether } { action_all() }<br />
Name <strong>of</strong> this rule<br />
NCL keyword<br />
Predicate<br />
Action<br />
The predicate part <strong>of</strong> the rule can be the name <strong>of</strong> a predicate defined earlier in the file<br />
or in an included file, or it can be a Boolean expression that can, in turn, use named<br />
predicates. A predicate uses packet protocol elements that are defined earlier in the<br />
NCL rules file or in an included file. You access protocol fields using the form<br />
protocol_name.field_name; for example, ip.src. In a predicate, the name <strong>of</strong> the<br />
protocol currently being parsed evaluates to TRUE.<br />
The action part <strong>of</strong> the rule contains the name <strong>of</strong> an action function defined in the<br />
compiled action code that is part <strong>of</strong> the same <strong>ACE</strong>. You can pass arguments to the<br />
function, as required by its definition. The action is executed only when and if the<br />
predicate part <strong>of</strong> the rule evaluates to TRUE.<br />
Classifying Packets Using NCL 101<br />
Revision 3.3, August 2001
Defining Protocols<br />
Defining Protocols<br />
A rule determines whether its predicate is true by looking at fields in the current<br />
packet. The fields are interpreted according to the protocol definitions in the NCL<br />
rules file.<br />
A protocol definition names and describes a protocol. It names and describes the<br />
header fields that make up the protocol, and describes the relationship among<br />
multiple protocols. You generally define protocols in the first main section <strong>of</strong> an NCL<br />
rules file, immediately after the file inclusions and constant definitions, and before<br />
the rules.<br />
The <strong>IXA</strong> <strong>SDK</strong> distribution contains an NCL include file that defines the TCP/IP<br />
protocol. You can include this file in your application, and also use it as a template for<br />
defining other protocols. The sample file is located in the following directory:<br />
<strong>SDK</strong>installpath/include/ix/ncl/ix_tcp.ncl<br />
Protocols <strong>of</strong>ten contain other protocols. The keyword demux in a protocol definition<br />
identifies other protocols that can be nested within it. (The keyword comes from<br />
demultiplexing, the process <strong>of</strong> extracting nested protocols from the protocols that<br />
contain them.) When a packet arrives, the IXP1200 parses the protocol definitions to<br />
classify the packet. When it reaches the demux statement, the parser evaluates the<br />
expressions in the order in which they appear. The first expression that evaluates to<br />
TRUE identifies the nested protocol, and the parser continues into the indicated<br />
protocol definition.<br />
For example, the IP protocol definition contains the following demux statement that<br />
specifies what other protocols could be nested in an IP packet, and at what <strong>of</strong>fset they<br />
would be found:<br />
demux {<br />
invalid { ip_bad at 0 }<br />
badsrc { ip_badsrc at 0 }<br />
(proto == 1) { icmp at hlen }<br />
(proto == 2) { igmp at hlen }<br />
(proto == 6) { tcp at hlen }<br />
(proto == 17) { udp at hlen }<br />
default { ip_unknown_transport at hlen }<br />
}<br />
While a protocol is being parsed, the protocol’s name becomes a Boolean expression<br />
that evaluates to TRUE. For example, if the IP protocol is currently being parsed, the<br />
expression ip evaluates to TRUE.<br />
The following example shows an excerpt from the NBtcpip.ncl include file. This<br />
excerpt defines the header fields for Ethernet packets, defines a reusable Boolean<br />
function (predicate) for the protocol, and specifies the demultiplexing (demux)<br />
method to high-layer protocols.<br />
102 Classifying Packets Using NCL<br />
Revision 3.3, August 2001
How Rules Are Evaluated<br />
protocol ether {<br />
NCL protocol definition<br />
dst { ether[0:6] }<br />
NCL field definition<br />
src { ether[6:6] }<br />
typelen { ether[12:2] }<br />
snap { ether[14:6] }<br />
NCL predicate description<br />
type { ether[20:2] }<br />
predicate isnap { (typelen
What Rules Do<br />
For more information on what actions can be taken and how to define them, see<br />
Chapter 10, “Initializing and Acting on Packets in an <strong>ACE</strong>.”<br />
What Rules Do<br />
A rule can simply check the protocol type and take an appropriate action. For<br />
example, a VPN application might have a rule to check for an IPSec packet. When the<br />
rule succeeds, the action decrypts the packet. The rule might look like this:<br />
rule check_ipsec { ipsec } { action_decrypt () }<br />
A rule can pass field values to the action. For example, the following rule passes the<br />
source and destination addresses:<br />
rule check_ip { ip } { action_ip (ip.src, ip.dst) }<br />
The rule itself can check the source or destination address, or both, against a particular<br />
address, or table <strong>of</strong> addresses.<br />
A rule that checks a specific address might look like this:<br />
rule check_src { ip.src == 10.10.10.30 } { action_A() }<br />
You can use sets to keep tables <strong>of</strong> addresses, and named searches to check incoming<br />
packet addresses against the table. For more information on sets and searches, see<br />
Chapter 13, “Using Sets <strong>of</strong> Data to Classify Packets.”<br />
The rule can check other fields in the packet. For example, in an intrusion detection<br />
application, a rule might check whether a TCP packet is part <strong>of</strong> an HTTP stream. The<br />
rule might look like this:<br />
rule check_http { tcp && (tcp.sport == 80 || tcp.dport == 80) }<br />
{ action_scan () }<br />
When successful, this rule passes the packet to an action function, where it is queued,<br />
reordered, and then searched for interesting strings. If the function finds such a<br />
string, it sends a notification to the control module using a crosscall.<br />
For more information on:<br />
l Defining action functions, see Chapter 10, “Initializing and Acting on Packets in<br />
an <strong>ACE</strong>.”<br />
l<br />
Crosscalls, see Chapter 11, “Communication Within an Application.”<br />
104 Classifying Packets Using NCL<br />
Revision 3.3, August 2001
Chapter 10<br />
Initializing and Acting on Packets in an <strong>ACE</strong><br />
This chapter describes the initialization and action phases <strong>of</strong> an <strong>ACE</strong>. It explains what<br />
is in the <strong>ACE</strong>’s C code files, how to write them, and what kind <strong>of</strong> things an <strong>ACE</strong><br />
might do.<br />
This chapter contains the following topics:<br />
l “<strong>ACE</strong> Code Overview” on page 105<br />
l “Initializing the <strong>ACE</strong>” on page 106<br />
l “Defining Action and Utility Functions” on page 108<br />
l “What Action Functions Do” on page 110<br />
<strong>ACE</strong> Code Overview<br />
Each <strong>ACE</strong> executable contains a C initialization file, linked with a C action file that is<br />
associated with an NCL rules file.<br />
l<br />
l<br />
The initialization file creates and initializes the <strong>ACE</strong> object, and also creates and<br />
initializes any other subclasses, objects, and structures that the <strong>ACE</strong> will need.<br />
The entry point is the application-defined ix_init function, which acts as a main<br />
function for the <strong>ACE</strong>. A corresponding ix_fini function cleans up upon exit by<br />
destroying all objects created during initialization.<br />
The action file contains the action and callback function definitions. These are<br />
entry points that implement the behavior <strong>of</strong> your application in response to<br />
incoming packets, crosscalls, or application-defined events. The action part also<br />
contains any other utility functions that your application might call from the entry<br />
point functions.<br />
Revision 3.3, August 2001<br />
Initializing and Acting on Packets in an <strong>ACE</strong> 105
Initializing the <strong>ACE</strong><br />
You write <strong>ACE</strong> initialization and action code using the following:<br />
l<br />
l<br />
The C/C++ runtime environment<br />
The action services library (ASL), which provides:<br />
— Support for the <strong>ACE</strong> structure and model, including a basic structure for<br />
representing network data packets (the ix_buffer), and for sending them to<br />
different destinations on the network (the ix_target)<br />
— Support for associating application-defined data with packets using data sets<br />
— Support for scheduling application-defined events<br />
The ASL API is described in detail in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Initializing the <strong>ACE</strong><br />
In the initialization portion <strong>of</strong> your action code file, you define any subclasses or<br />
other data structures that the application will need. The initialization function,<br />
ix_init, must create and initialize the <strong>ACE</strong> itself, as well as any other objects and<br />
data the <strong>ACE</strong> will need.<br />
Defining ASL<br />
Objects<br />
Each <strong>ACE</strong> executable file is associated with one <strong>ACE</strong>, which is represented by an<br />
ix_ace structure. Your initialization function must allocate such an object and<br />
initialize it by calling ix_ace_init.<br />
Normally, an application defines a customized <strong>ACE</strong> structure that contains an<br />
ix_ace and other associated objects and data. Your <strong>ACE</strong> initialization function must,<br />
in addition to creating the <strong>ACE</strong> itself, create and initialize all structures associated<br />
with the <strong>ACE</strong>. These can include:<br />
l<br />
l<br />
l<br />
l<br />
Target objects. Each <strong>ACE</strong> automatically includes a target named default, which<br />
you normally bind to the egress network interface <strong>ACE</strong> or to the next <strong>ACE</strong> in the<br />
processing pipeline. You can also define additional targets to bind to other destinations.<br />
For more information, see Chapter 5, “Controlling Packet Flow.”<br />
Communication objects. These include crosscall and crosscall reference objects,<br />
from subclasses produced by the IDL compiler and customized with your application’s<br />
crosscall methods. For deferred crosscalls, you must also define and set<br />
the crosscall callback function. For more information, see Chapter 11, “Communication<br />
Within an Application.”<br />
Data set and set element objects. For each data set, the <strong>ACE</strong> initialization must<br />
declare and create a set structure (ix_set) with the same name and size that was<br />
declared for the set in NCL. It might also populate the set on initialization. For<br />
more information, see Chapter 13, “Using Sets <strong>of</strong> Data to Classify Packets.”<br />
Event objects. These allow you to schedule application-defined events for the<br />
<strong>ACE</strong>. In addition to creating and initializing the event structure (ix_event), you<br />
must define and set an event callback function to perform the desired operation.<br />
106 Initializing and Acting on Packets in an <strong>ACE</strong><br />
Revision 3.3, August 2001
Initializing the <strong>ACE</strong><br />
Your <strong>ACE</strong> also typically contains methods or functions to perform applicationspecific<br />
operations, such as invoking crosscalls or initiating searches, as well as callback<br />
functions for crosscalls and events. For more information, see “Defining Callbacks”<br />
on page 109 and “Defining Utility Functions” on page 109.<br />
Defining the<br />
Initialization<br />
Function<br />
Your <strong>ACE</strong> initialization file must contain a definition for the “main” function for the<br />
<strong>ACE</strong>, ix_init(). In this function, you must create and return the ix_ace object for<br />
the <strong>ACE</strong> to which the code belongs. In addition to creating the <strong>ACE</strong> object, the function<br />
must perform any other initialization the <strong>ACE</strong> needs. It must create targets and<br />
other associated objects and structures, populate sets, or initialize other data structures.<br />
The following is an example <strong>of</strong> an application-defined <strong>ACE</strong> initialization function<br />
that creates an <strong>ACE</strong> containing one target in addition to the default, named<br />
MyTarget:<br />
ix_error ix_init (int argc, char **argv, ix_ace **acep)<br />
{<br />
//allocate ace, pass to ace init<br />
ix_ace myace;<br />
ix_target mytarget;<br />
}<br />
ix_ace_init (myace, argv[1]); //name <strong>of</strong> <strong>ACE</strong> is passed in<br />
ix_target_init (mytarget, myace, "MyTarget");<br />
// error case<br />
// (error handling code here)<br />
//success, return<br />
acep = myace;<br />
return 0;<br />
The Resolver calls the <strong>ACE</strong>’s ix_init function when the application creates an <strong>ACE</strong>.<br />
A manager program can create the <strong>ACE</strong> by calling ix_res_create_ace(), passing<br />
the name <strong>of</strong> the <strong>ACE</strong> as its first argument. (See Chapter 2, “OMS Global Services<br />
API,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.) You can also create the <strong>ACE</strong> directly from the<br />
command line or a script, using the utility ixace. (See Chapter 8, “Command-Line<br />
Tools,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.)<br />
The <strong>ACE</strong> initialization process automatically creates a CAP through which the <strong>ACE</strong><br />
can communicate with the OMS, and starts the <strong>ACE</strong> loop, which listens for packet<br />
arrival and crosscall events.<br />
The <strong>ACE</strong> loop continues to run until the manager module deletes the <strong>ACE</strong> by calling<br />
ix_res_delete_ace, which in turn calls the <strong>ACE</strong>’s ix_fini function. The <strong>ACE</strong>’s<br />
action code must contain a definition for the function ix_fini which correctly<br />
deletes all objects and structures created during initialization.<br />
Initializing and Acting on Packets in an <strong>ACE</strong> 107<br />
Revision 3.3, August 2001
Defining Action and Utility Functions<br />
Defining Action and Utility Functions<br />
The action code file must define the methods and functions that implement the<br />
behavior <strong>of</strong> your application. You can implement behavior in any <strong>of</strong> the following<br />
ways:<br />
l<br />
l<br />
l<br />
Action functions<br />
An action function is executed when an NCL rule’s predicate is TRUE for an<br />
incoming packet. Action functions can call methods or other functions directly, or<br />
schedule events that result in the execution <strong>of</strong> callbacks.<br />
Callbacks<br />
Callbacks are executed in response to crosscall completions or scheduled events.<br />
You define a callback as a function <strong>of</strong> the appropriate type.<br />
Other utility functions<br />
You must provide definitions for utility functions. These are not entry points. To<br />
execute a utility function, you must call it from an action function or callback.<br />
Defining<br />
Action<br />
Functions<br />
Actions are function entry points implemented according to the calling conventions<br />
<strong>of</strong> the C/ C++ programming language. An action function is executed when an NCL<br />
rule predicate is satisfied for an incoming packet. The rule must pass any arguments<br />
that you have defined for the action function, and the action function must return one<br />
<strong>of</strong> the disposition codes that tell the <strong>ACE</strong> whether to continue passing the packet to<br />
other action functions triggered by successful classification rules.<br />
NOTE:<br />
Due to limitations in the gcc compiler, it is recommended that you avoid the<br />
use <strong>of</strong> type bool arguments in action functions. Use unsigned int instead.<br />
Action Function Return Values<br />
An action function that you define must return one <strong>of</strong> the following constant values:<br />
Constant Value Description<br />
RULE_CONT 0 Return RULE_CONT if the action has only observed the<br />
buffer, and additional rules and actions within the context <strong>of</strong><br />
the current <strong>ACE</strong> remain to be processed.<br />
Return this value from functions that do not take ownership<br />
<strong>of</strong> the network packet buffer.<br />
RULE_DONE 1 Return RULE_DONE to terminate processing <strong>of</strong> rules and<br />
actions within the context <strong>of</strong> the current <strong>ACE</strong>, for example,<br />
when a buffer has been sent to a target or stored for later<br />
processing.<br />
Return this value from functions that take ownership <strong>of</strong> the<br />
network packet buffer.<br />
108 Initializing and Acting on Packets in an <strong>ACE</strong><br />
Revision 3.3, August 2001
Defining Action and Utility Functions<br />
CAUTION: If your action function does not return one <strong>of</strong> these codes, your application<br />
can be corrupted when the action function returns, and the corruption may<br />
not be detectable.<br />
Predefined Default Action Function<br />
One action function, ix_action_default, is already defined in the ASL. This function<br />
routes a packet to the <strong>ACE</strong>’s default target. It returns the code RULE_DONE, which<br />
halts all further processing for the packet. It take no arguments. To call this function<br />
in an NCL rule, use a rule like the following:<br />
rule passip { ip } { ix_action_default() }<br />
This would pass all IP packets through to the <strong>ACE</strong>’s default target without further<br />
processing.<br />
For More Information<br />
For more information on defining action functions, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Defining<br />
Callbacks<br />
In the action part <strong>of</strong> your action code file, you define the callbacks that are executed<br />
in response to various events. You can define the following kinds <strong>of</strong> callbacks:<br />
l<br />
l<br />
Deferred crosscall callbacks<br />
The callback or service function for a crosscall implements the behavior to be<br />
executed when a deferred crosscall is completed.<br />
The <strong>IXA</strong> IDL compiler generates a skeleton for each crosscall callback function,<br />
which takes as its arguments the output parameters defined for the corresponding<br />
call in the crosscall interface. You must modify the skeleton to define the<br />
behavior <strong>of</strong> the function.<br />
For more information on call handler callbacks, see Chapter 11, “Communication<br />
Within an Application.”<br />
Scheduled event callbacks<br />
The ix_event mechanism provides for execution <strong>of</strong> functions at arbitrary times<br />
in the future. An action function can schedule, reschedule, or cancel an event, or<br />
change the function that it executes. The event callback function implements the<br />
behavior to be executed at the scheduled time.<br />
For more information on event callbacks, see Chapter 4, “The ASL Core Support<br />
Package API,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Defining Utility<br />
Functions<br />
You can define utility functions in the action file, be called from entry points such as<br />
action functions and callbacks. For example, an <strong>ACE</strong> that serves as a crosscall client<br />
typically contains a utility function to build a message and invoke a remote call, using<br />
the crosscall reference or stub. This utility function can be called, for example, by an<br />
action function in response to the receipt <strong>of</strong> a packet containing specific information.<br />
Initializing and Acting on Packets in an <strong>ACE</strong> 109<br />
Revision 3.3, August 2001
What Action Functions Do<br />
What Action Functions Do<br />
You can define action functions to respond to the successful application <strong>of</strong> a rule in<br />
any way you want. Actions can do any <strong>of</strong> the following:<br />
l<br />
l<br />
l<br />
l<br />
Pass the current packet to any target<br />
Modify a packet before passing it to a target<br />
Increment and decrement application-specific counters<br />
Schedule an event for execution at a later time<br />
l Build and send messages using crosscalls. For more information, see Chapter 11,<br />
“Communication Within an Application.”<br />
l<br />
l<br />
Maintain data sets, creating elements to insert in a set, and deleting elements after<br />
removing them from a set. For more information, see Chapter 13, “Using Sets <strong>of</strong><br />
Data to Classify Packets.”<br />
Call other functions or methods<br />
The following table shows some typical actions you might define for different types<br />
<strong>of</strong> applications. Notice that, while the action is triggered by a rule that checks a particular<br />
condition, the action itself can continue to check conditions before deciding what<br />
to do.<br />
Table 1:<br />
Application Type Classification Action<br />
Firewall<br />
Controls access by maintaining<br />
a set <strong>of</strong> acceptable source<br />
addresses<br />
If packet IP source<br />
address is in my table <strong>of</strong><br />
addresses that have<br />
access to my network<br />
Route the packet to the<br />
appropriate location inside<br />
my network<br />
Firewall<br />
Translates packet addresses<br />
based on a set <strong>of</strong> address<br />
mappings<br />
If packet IP destination<br />
address matches a<br />
known address for<br />
inbound traffic<br />
If the packet IP source<br />
address matches a<br />
known address for outbound<br />
traffic<br />
Change the destination<br />
address to the new address<br />
specified by the matching<br />
set element<br />
Recompute checksums<br />
Change the source address<br />
back to the original mapping<br />
address specified in<br />
the matching set element<br />
Recompute checksums<br />
110 Initializing and Acting on Packets in an <strong>ACE</strong><br />
Revision 3.3, August 2001
What Action Functions Do<br />
Table 1: (Continued)<br />
Application Type Classification Action<br />
Load-balancing<br />
Redirects packets to leastloaded<br />
servers by maintaining<br />
a set <strong>of</strong> possible destination<br />
servers<br />
If the IP source and destination<br />
match an element<br />
in the server set<br />
If the IP source and destination<br />
do not match any<br />
element in the server set,<br />
pass the pointer to where<br />
the record should go to<br />
the action<br />
Perform address translation<br />
(NAT) to change destination<br />
to value from matching<br />
element<br />
Recompute the checksum<br />
Send the packet to the identified<br />
server<br />
Use a load-balancing algorithm<br />
to determine the<br />
server to which the connection<br />
should go<br />
Create a new element for<br />
the server and add it to the<br />
set<br />
Perform NAT on the packet<br />
and send it to the identified<br />
server<br />
Intrusion detection<br />
Network monitoring<br />
If the packet is part <strong>of</strong> a<br />
TCP stream<br />
If the packet is HTTP and<br />
has a specified IP source<br />
address<br />
Search the packet for interesting<br />
strings<br />
If found, notify the application<br />
using an upcall<br />
Search the packet for the<br />
name <strong>of</strong> the web page <strong>of</strong><br />
interest<br />
If found increment a<br />
counter called mywebpage<br />
Quality <strong>of</strong> service<br />
Maintains higher and lower<br />
priority queues for transmitting<br />
traffic<br />
If the IP destination<br />
address equals that <strong>of</strong> an<br />
internal server<br />
If the IP source address<br />
equals that <strong>of</strong> a preferred<br />
customer<br />
Place the packet on a high<br />
priority queue for transmission<br />
Place the packet on a high<br />
priority queue for transmission<br />
If the IP destination<br />
address is an external<br />
web site and the source<br />
address is from a low-priority<br />
department<br />
Place the packet on a low<br />
priority queue for transmission<br />
VPN<br />
If the packet is an IPSec<br />
packet<br />
Decrypt the packet using<br />
cryptographic API calls.<br />
Initializing and Acting on Packets in an <strong>ACE</strong> 111<br />
Revision 3.3, August 2001
What Action Functions Do<br />
112 Initializing and Acting on Packets in an <strong>ACE</strong><br />
Revision 3.3, August 2001
Chapter 11<br />
Communication Within an Application<br />
This chapter introduces the crosscall mechanism that is used for communication<br />
between s<strong>of</strong>tware objects through the Object Management System (OMS). It contains<br />
the following topics:<br />
l “Overview” on page 113<br />
l “Defining Crosscall Interfaces” on page 116<br />
l “Defining Call Operations” on page 118<br />
l “Invocation Types for Operations” on page 120<br />
l “Initializing and Terminating Interfaces” on page 125<br />
l “Invoking Crosscall Functions” on page 130<br />
l “Passing Crosscall Arguments” on page 133<br />
Overview<br />
<strong>ACE</strong>s <strong>of</strong>ten need to communicate with one another or with a managing program for<br />
various reasons. For example:<br />
l<br />
l<br />
l<br />
l<br />
<strong>ACE</strong>s can send alerts or status reports to a managing program.<br />
Data processor <strong>ACE</strong>s can receive control messages and data from control <strong>ACE</strong>s.<br />
Data processor <strong>ACE</strong>s can send occasional packet data to control <strong>ACE</strong>s for special<br />
processing<br />
<strong>ACE</strong>s can exchange messages among themselves to coordinate packet processing.<br />
Because <strong>ACE</strong>s and their managing programs might be running on different platforms<br />
and be written in different languages, the <strong>IXA</strong> provides a communication mechanism<br />
based on remote procedure calls. The remote calls that you define for an <strong>IXA</strong> application<br />
are known as crosscalls.<br />
Revision 3.3, August 2001<br />
Communication Within an Application 113
Overview<br />
The OMS acts as a message broker for crosscalls. It provides marshalling and format<br />
conversion to handle differences in byte order and word size between different<br />
processors.<br />
Defining<br />
Interfaces<br />
You do not need to implement the entire crosscall infrastructure in your application.<br />
Instead, you define an interface, using an interface definition language, <strong>IXA</strong> IDL, that<br />
is provided with the <strong>IXA</strong> <strong>SDK</strong>. In the interface definition file you create a prototype<br />
for each operation, which determines whether a call is synchronous or asynchronous<br />
as well as defining the return type and argument types and directions for each call.<br />
In addition to the call prototypes, the interface definition file includes definitions for<br />
data structures used by the crosscalls.<br />
You compile an <strong>IXA</strong> IDL interface definition using the supplied compiler, tao_idl.<br />
The compiler generates several C source and header files that implement the calling<br />
infrastructure. You include the generated code with your application code. The only<br />
additional code you need to write is the implementation <strong>of</strong> the application-specific<br />
crosscall behavior. The compiler supplies template functions with the proper calling<br />
protocol, based on the interface you defined.<br />
Making and<br />
Receiving<br />
Remote Calls<br />
An <strong>ACE</strong> or an external object can both make and receive remote function calls. An<br />
object that receives calls acts as a crosscall server. An object that makes calls acts as a<br />
crosscall client.<br />
l<br />
l<br />
The call server receives the call from the client and executes the call function.<br />
Depending on how you define the crosscall interface, it can send a response to the<br />
client or not. The server contains the crosscall function implementation, as well as<br />
the generated code for the calling infrastructure.<br />
The call client makes a remote call to the call server. It contains a generated crosscall<br />
reference stub function, as well as generated code for the calling infrastructure.<br />
Depending on the type <strong>of</strong> call, it can also contain a callback function for handling<br />
an asynchronous response from the server.<br />
An <strong>ACE</strong> or task can act as a server for more than one crosscall, and can act as a client<br />
for any number <strong>of</strong> crosscalls as well.<br />
Crosscall<br />
Client<br />
Crosscall<br />
Server<br />
Crosscall<br />
Client<br />
Crosscall<br />
Client<br />
Crosscall<br />
Client<br />
Crosscall<br />
Server<br />
Crosscall<br />
Server<br />
114 Communication Within an Application<br />
Revision 3.3, August 2001
Overview<br />
Each call client or server must open a communication session with OMS. The session<br />
requires a dedicated communications channel called a communication access process<br />
(CAP). The call client or server can be either an <strong>ACE</strong> or a non-<strong>ACE</strong> program.<br />
l<br />
l<br />
When you create an <strong>ACE</strong>, the initialization procedure automatically creates a<br />
CAP for that <strong>ACE</strong>, and the <strong>ACE</strong> runtime polls that CAP for crosscall events in its<br />
main loop. When you initialize crosscalls, extract the <strong>ACE</strong>’s CAP using<br />
ix_ace_to_cap.<br />
A non-<strong>ACE</strong> program that acts as a crosscall client or server must initialize itself<br />
with the OMS as a task, using the ASL function ix_task_init. You can add the<br />
task to the OMS name space using the function ix_ns_add_task.<br />
Run the crosscall session in a separate thread. When you initialize crosscalls,<br />
extract the task’s CAP using ix_task_to_cap. The thread must poll the CAP for<br />
crosscall events using ix_cap_loop.<br />
Application code<br />
CAP, crosscall reference<br />
Remote procedure call<br />
Client task<br />
OMS<br />
Optional response<br />
Packet<br />
flow<br />
CAP, crosscall<br />
Packet Related<br />
classification actions<br />
Server <strong>ACE</strong><br />
When to Use<br />
Crosscalls<br />
Applications typically use crosscalls for configuration. For example, predefined<br />
library <strong>ACE</strong>s and system <strong>ACE</strong>s export crosscall interfaces that allow your application<br />
to configure them by making remote calls.<br />
Crosscalls are not an efficient way to forward packets. You can use a crosscall to send<br />
an occasional packet to another <strong>ACE</strong> for special processing or examination, or to send<br />
data retrieved from a packet. However, applications should use targets rather than<br />
crosscalls to pass packets between <strong>ACE</strong>s in the course <strong>of</strong> normal processing, as the<br />
target mechanism is optimized for packet traffic and is much more efficient.<br />
Communication Within an Application 115<br />
Revision 3.3, August 2001
Defining Crosscall Interfaces<br />
Defining Crosscall Interfaces<br />
You define a crosscall interface for an <strong>ACE</strong> or other object in a .idl file, using the <strong>IXA</strong><br />
Interface Definition Language (<strong>IXA</strong> IDL). The syntax and grammar <strong>of</strong> the <strong>IXA</strong> IDL,<br />
which is similar to C/C++, is completely described in Chapter 7, “<strong>IXA</strong> Interface Definition<br />
Language (<strong>IXA</strong> IDL),” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
An <strong>IXA</strong> IDL compiler is provided with the <strong>IXA</strong> <strong>SDK</strong>. This compiler converts <strong>IXA</strong> IDL<br />
files into customized C files for making remote function invocations. In creating these<br />
C files, the compiler transparently handles hardware dependent issues such as types,<br />
byte order, and alignment. You never need to write C code for the OMS interaction.<br />
Generated<br />
Files<br />
The compiler generates file names by appending a suffix to the <strong>IXA</strong> IDL source file<br />
name for skeleton, crosscall, stub, and callback files. From the source file<br />
idlname.idl, the <strong>IXA</strong> IDL compiler produces the following C files:<br />
Server/Client Generated Files Description<br />
Server only idlname_sk_c.h Crosscall skeleton header.<br />
idlname_sk_c.c<br />
idlname_cc_c.h<br />
idlname_cc_c.c<br />
Crosscall skeleton source.<br />
Crosscall template header, includes skeleton<br />
header.<br />
Crosscall template source, includes skeleton<br />
source.<br />
Use the crosscall template as base for<br />
implementation.<br />
Server and client idlname_stub_c.h Crosscall reference header.<br />
idlname_stub_c.c Crosscall reference source.<br />
idlname_cb_c.h<br />
idlname_cb_c.c<br />
Callback template header.<br />
Callback template source.<br />
Use the callback template as a base for<br />
implementation if there are any deferred<br />
calls.<br />
l<br />
l<br />
Skeletons: These files contain all the code needed for the interaction between the<br />
crosscall (server), the crosscall reference (client), and the OMS.<br />
Use these files without modification. Include the header in the server’s source<br />
code, and link the source file into the server’s executable.<br />
Crosscalls: For each operation, the crosscall template file contains a function<br />
template, and a crosscall virtual method table (VMT) that points to the function<br />
implementations.<br />
Include the header file in the crosscall server’s source code, and link the source<br />
file into the server’s executable. Initialize crosscalls in the server using the generated<br />
initialization functions provided in this file.<br />
116 Communication Within an Application<br />
Revision 3.3, August 2001
Defining Crosscall Interfaces<br />
Use the function templates as a model to provide the call function implementations.<br />
To avoid losing your changes on recompilation, keep the implementations<br />
in a separate source file. Replace the VMT pointers to the template functions with<br />
pointers to your implementations.<br />
l<br />
l<br />
Stubs: These files implement the crosscall reference stub functions, and also<br />
contain infrastructure needed by the server. Use these files without modification.<br />
Include the header in both the client’s and the server’s source code, and link the<br />
source files into the client’s and server’s executables. Initialize crosscalls in the<br />
client using the generated initialization functions provided in this file.<br />
Callbacks: For any deferred call operations, the compiler creates template callback<br />
functions in these files. (See “Invocation Types for Operations” on page 120.) If<br />
there are no deferred operations, these files are empty. When there are callback<br />
functions, the files contain a callback virtual method table (VMT) that points to<br />
the function implementations.<br />
If there are callback functions, include the header in both the client’s and the<br />
server’s source code, and link the source files into the client’s and server’s executables.<br />
Use the templates as a model to provide the callback function implementations.<br />
To avoid losing your changes on recompilation, keep the implementations in a<br />
separate source file. Replace the VMT pointers to the template functions with<br />
pointers to your function implementations.<br />
Organizing<br />
Call<br />
Operations<br />
<strong>IXA</strong> IDL files are structured as a set <strong>of</strong> modules, which, in turn, are composed <strong>of</strong> one<br />
or more interfaces and data structure definitions.<br />
l<br />
l<br />
Each module defines a name space or scope for a set <strong>of</strong> interfaces. You can use<br />
modules to group interfaces, so that you can repeat common operation names<br />
(such as ReportError, for example). Interface names must be unique only within<br />
a module.<br />
Each interface contains the signatures <strong>of</strong> individual operations. Operation names<br />
must be unique only within an interface. Each operation maps to one crosscall<br />
server function and its stub client function. Each deferred operation also maps to<br />
a callback function for handling the asynchronous response.<br />
An <strong>IXA</strong> IDL file can contain more than one interface. <strong>ACE</strong>s and other objects can<br />
import or export more than one interface. Each interface can contain one or more<br />
operations.<br />
You can divide individual call operations among interfaces, or define them all in a<br />
single interface, depending on how you want to organize your application’s functionality.<br />
For example, here is a sample IDL file that defines three crosscall interface definitions,<br />
each containing two operation call signatures, in one module:<br />
module myXcalls<br />
{<br />
interface XcallOne<br />
{<br />
//....<br />
Communication Within an Application 117<br />
Revision 3.3, August 2001
Defining Call Operations<br />
XcallOneFn1 (args);<br />
XcallOneFn2 (args);<br />
//....<br />
};<br />
interface XcallTwo<br />
{<br />
//....<br />
XcallTwoFn1 (args);<br />
XcallTwoFn2 (args);<br />
//....<br />
};<br />
interface XcallThree<br />
{<br />
//....<br />
XcallThreeFn1 (args);<br />
XcallThreeFn2 (args);<br />
//....<br />
};<br />
};<br />
Alternatively, you could define and create a single crosscall that exports all six operations:<br />
module myXcalls<br />
{<br />
interface XcallOneTwoThree<br />
{<br />
//....<br />
XcallOneFn1 (args);<br />
XcallOneFn2 (args);<br />
XcallTwoFn1 (args);<br />
XcallTwoFn2 (args);<br />
XcallThreeFn1 (args);<br />
XcallThreeFn2 (args);<br />
//....<br />
};<br />
The two approaches are equally valid. In either case the compiler generates eight<br />
files. Using separate interface definitions to group operations functionally can make<br />
your code more readable.<br />
Defining Call Operations<br />
In each operation signature in an interface definition you declare the return type, the<br />
directions and types <strong>of</strong> all arguments, and the invocation form. Together, these determine<br />
whether and how values can be returned from the remote function invocation.<br />
118 Communication Within an Application<br />
Revision 3.3, August 2001
Defining Call Operations<br />
Operation<br />
Names<br />
You name each operation in an interface definition, but the operation name is unique<br />
only within the interface. Similarly, the interface name is unique only within a<br />
module. To translate this scoping and create unambiguous names, the <strong>IXA</strong> IDL<br />
compiler produces function names by prepending the module and interface names<br />
to the operation name.<br />
For example, the following interface definition repeats the operation names in two<br />
interfaces:<br />
module mod1<br />
{<br />
interface if1<br />
{<br />
op1 (args);<br />
op2 (args);<br />
};<br />
interface if2<br />
{<br />
op1 (args);<br />
op2 (args);<br />
};<br />
};<br />
In the crosscall source file that results from compilation, the function skeletons are<br />
named as follows:<br />
mod1_if1_op1<br />
mod1_if1_op2<br />
mod1_if2_op1<br />
mod1_if2_op1<br />
If the interface definition includes nested modules or interfaces, they are included in<br />
the generated name from the outside in. For example, in the following interface definition,<br />
module mod2 is nested inside module mod1:<br />
module mod1<br />
{<br />
interface if1<br />
{<br />
op1 (args);<br />
op2 (args);<br />
};<br />
{module mod2<br />
interface if2<br />
{<br />
op1 (args);<br />
op2 (args);<br />
};<br />
};<br />
};<br />
In this case, the generated names for the two op1 operations in the two modules are<br />
as follows:<br />
Communication Within an Application 119<br />
Revision 3.3, August 2001
Invocation Types for Operations<br />
mod1_if1_op1<br />
mod1_mod2_if2_op1<br />
Invocation Types for Operations<br />
There are three forms <strong>of</strong> remote function invocation, which determine whether the<br />
caller receives a response, and if so whether it is synchronous or asynchronous:<br />
l<br />
l<br />
l<br />
One-way calls receive no response.<br />
Two-way calls elicit a synchronous response. The OMS blocks the caller until it<br />
receives the response. (This form can only be used by external crosscall clients.<br />
<strong>ACE</strong>s cannot block.)<br />
Deferred calls allow an asynchronous response. The call returns immediately with<br />
a simple result indicating whether the call was successfully sent. When the call<br />
completes the OMS invokes a callback handler specified by the caller.<br />
You declare the type <strong>of</strong> an operation with a keyword before the operation signature<br />
in the interface definition. The type <strong>of</strong> the operation affects how input and output<br />
arguments are mapped to the generated functions. For more information, see<br />
“Passing Crosscall Arguments” on page 133.<br />
One-way<br />
Operations<br />
When a client calls a one-way function, the object calling the function does not block.<br />
It makes the call and then immediately continues processing, while the remote object<br />
executes the remote function.<br />
l<br />
l<br />
Declare a one-way operation using the keyword oneway before the return type<br />
declaration in the operation signature.<br />
A one-way function invocation cannot return a value. Therefore, you must<br />
declare the return value as void and all parameters as in.<br />
Since the calling object has no way <strong>of</strong> knowing whether the function executed<br />
successfully, use the one-way operation where such knowledge is not essential or<br />
where the success <strong>of</strong> the function call is tested by invoking another function.<br />
The following example shows the signature for a one-way operation in an interface<br />
definition:<br />
oneway void doSomething(in char* name);<br />
The generated skeleton and stub functions for this call are defined to take the input<br />
argument, and return an error token (ix_error) .<br />
Two-way<br />
Operations<br />
When a client calls a two-way function, the calling object blocks (waits for the function<br />
to execute and return) before continuing its own processing. This allows the<br />
remote object to respond, and the caller to determine the success <strong>of</strong> the execution.<br />
l<br />
Declare a two-way operation using the keyword twoway before the return type<br />
declaration in the operation signature. This is the default invocation type, so if<br />
you do not declare the type, the operation is two-way.<br />
120 Communication Within an Application<br />
Revision 3.3, August 2001
Invocation Types for Operations<br />
l<br />
l<br />
A two-way operation can have output arguments. You can use these to return<br />
values from the remote object.<br />
A two-way operation can return a value. The compiler maps the return value to<br />
an output argument before generating the C code.<br />
NOTE:<br />
This form can only be used by external crosscall clients. <strong>ACE</strong>s cannot block.<br />
They can serve two-way calls, but cannot be clients for them.<br />
Here is an example <strong>of</strong> the prototype for a two-way operation in an interface definition:<br />
twoway void doSomething(in int value, out char* name);<br />
This operation has an out parameter that will return a value to the caller.<br />
All generated functions return an ix_error error token. The generated stub function<br />
(that the client uses to invoke the call remotely) is defined to take both the input and<br />
the output argument. For output arguments in a two-way function, the call client<br />
must allocate a variable <strong>of</strong> the proper type and pass its address to the call stub function.<br />
Upon return, the stub function places the output data in the output variable.<br />
Deferred<br />
Operations<br />
In a deferred operation, the calling object expects the remote function to execute and<br />
return but does not block processing until a response is received. It calls the stub function<br />
and then immediately continues processing, while the remote object executes the<br />
remote function. The calling object stores a callback function in a common data area<br />
and executes the callback when a reply is received from the remote function that was<br />
called. In this case, the caller can determine the success <strong>of</strong> the execution <strong>of</strong> the function<br />
on the remote object by the remote object response.<br />
l<br />
l<br />
l<br />
Declare a deferred operation using the keyword deferred before the return type<br />
declaration in the operation signature.<br />
A deferred operation can have output arguments which are passed to the callback<br />
function.<br />
A deferred operation can return a value. The compiler maps the return value to<br />
an output argument before generating the C code.<br />
Here is an example <strong>of</strong> the prototype for a deferred operation in an interface definition:<br />
deferred void doSomething (in int value, out char* name);<br />
The operation returns void but has an out parameter that will return a value to the<br />
callback function in the client.<br />
Handling Asynchronous Responses with a Callback Function<br />
When an interface contains a deferred operation, the compiler generates a template<br />
definition for a callback function in the callback header and source files. You must use<br />
the template to implement the callback function definition.<br />
Communication Within an Application 121<br />
Revision 3.3, August 2001
Invocation Types for Operations<br />
The generated stub function takes the input (in and inout) arguments. The OMS<br />
passes the output (inout and out) values to the callback function. All generated functions<br />
return an error token (ix_error). When the client allocates resources for a stub<br />
function variable, it is responsible for freeing those resources when the application no<br />
longer needs the value.<br />
The callback function template takes the following arguments:<br />
l The interface token, <strong>of</strong> type ix_base_t.<br />
l The error returned by the call function, <strong>of</strong> type ix_error.<br />
l All output (out and inout) arguments defined for the deferred call operation<br />
with which it is associated.<br />
For example, for the deferred operation defined above, the compiler generates a callback<br />
template with the following signature:<br />
ix_error mod1_if1_doSomething_cb (ix_base_t* basep, ix_error<br />
anError, char* name);<br />
Specifying<br />
Timeouts<br />
For two way and deferred operations, you can specify a timeout. For example:<br />
twoway long op1(in long val) context("TIMEOUT=5");<br />
The integer value determines the number <strong>of</strong> seconds the client will wait for a<br />
response before returning an error. If you do not specify a timeout, the default<br />
timeout value is determined by the OMS variable IX_OMS_SYSTEMTIMEOUT.<br />
You cannot specify a timeout <strong>of</strong> 0 seconds.<br />
Declaring<br />
Argument<br />
Directions<br />
Depending on the invocation type (see “Invocation Types for Operations” on<br />
page 120), a call can sometimes return values through output arguments. You declare<br />
operation arguments as input, output, or both input and output using the keywords<br />
in, out, and inout. The direction keyword precedes the type declaration for each<br />
argument.<br />
For example, the following operation signature declares a single input argument:<br />
oneway void accept_source(in appair_t appair);<br />
The following operation signature declares two arguments, where the first is input<br />
and the second is output:<br />
deferred void read_accept_list (in long listlen,<br />
out aplist_t aplist);<br />
The call function that the compiler generates for an operation must always return an<br />
ix_error. If you declare a return type for an operation in the interface definition, the<br />
compiler automatically transforms it to an output variable. For example, the declaration<br />
long op(); is transformed to:<br />
void op (out long _return_long)<br />
122 Communication Within an Application<br />
Revision 3.3, August 2001
Integrating Crosscalls with Applications<br />
The generated call template for an operation takes as parameters all declared arguments<br />
in the interface definition. In general, if a parameter can be used for output<br />
(out or inout), the caller must pass an address and you must define the call function<br />
to dereference it. For more information, see “Passing Crosscall Arguments” on<br />
page 133.<br />
The generated call reference stub takes all input arguments (in and inout), which it<br />
passes to the call function in the server. For a synchronous two-way operation, it also<br />
takes the addresses <strong>of</strong> output arguments (out and inout), which it uses to store<br />
response values.<br />
For an asynchronous deferred operation, the output (out and inout) arguments<br />
become parameters in the template callback function.<br />
Integrating Crosscalls with Applications<br />
To define a crosscall, use the following steps:<br />
1. Create a crosscall interface definition in <strong>IXA</strong> IDL file, file.idl.<br />
2. Compile the file on the command line, using the tao_idl compiler:<br />
> tao_idl file.idl<br />
The <strong>IXA</strong> IDL compiler generates code for both the client and server from the interface<br />
definition. The compiler output includes C source and header files that<br />
contain skeletons <strong>of</strong> the call functions, as well as stub functions with which to<br />
invoke them. These files implement the crosscall infrastructure.<br />
3. Include both the skeleton headers and the stub headers in the call server, and link<br />
the executable with the skeleton and stub C sources.<br />
4. Include the stub header in the call client, and link the executable with the stub<br />
source.<br />
5. For each operation in an interface definition, provide a crosscall function that<br />
actually implements the desired service, according to your application requirements.<br />
The compiler generates a template crosscall function for each operation, which<br />
you can use as a basis for your implementation.<br />
— For prototyping, you can modify the generated files directly. Include the<br />
generated crosscall header in the call server, and link the executable with the<br />
modified crosscall C source. However, the generated file is overwritten each<br />
time you compile the <strong>IXA</strong> IDL, and your changes are lost.<br />
— For a real application, write the crosscall definition in another source file,<br />
making sure it conforms to the template. During initialization, you must<br />
change the crosscall VMT structure to point to your crosscall implementation<br />
instead <strong>of</strong> to the template function.<br />
6. If the interface specifies any deferred (asynchronous) operations, provide a callback<br />
function implementation for each one. This is a function that is executed<br />
when the call completes.<br />
Revision 3.3, August 2001<br />
Communication Within an Application 123
Integrating Crosscalls with Applications<br />
The compiler produces a template callback function for each deferred operation.<br />
As for the crosscall template, you can modify the generated template to provide a<br />
callback definition, or provide an implementation based on the template in<br />
another file. You must change the callback VMT structure to point to your callback<br />
implementation instead <strong>of</strong> to the template function.<br />
7. Initialize each crosscall interface as part <strong>of</strong> the initialization process in both client<br />
and server. Initialization must be complete before the client makes any calls. See<br />
Appendix , “Communication Within an Application” on page 125.<br />
Threads and<br />
Crosscalls<br />
To make two-way calls, a client must use multithreading. If the call client is an <strong>ACE</strong>,<br />
which must be single-threaded, or if the client program needs to be single-threaded<br />
for any other reason, you must use deferred calls rather than two-way calls to return<br />
information to the caller. For a deferred call, you must define a callback function to<br />
handle the returned results, basing it on the template created by the <strong>IXA</strong> IDL<br />
compiler.<br />
An external program that communicates through the OMS is known as a task. To<br />
create the task, use the ASL function ix_task_init, and extract the CAP using<br />
ix_task_to_cap. Add the task to the Name Server using ix_ns_add_task. When<br />
the crosscall client opens a connection to the call server, it passes the task name. (See<br />
“Invoking Crosscall Functions” on page 130.)<br />
In communicating with the Name Server and Resolver, a task can use either an asynchronous<br />
session and entry points (ix_ns_open, ix_res_open) or a synchronous<br />
session and entry points (ix_ns_open_sync, ix_res_open_sync). Synchronous<br />
communication is easier to write and to read, although it requires a separate thread<br />
for the session. <strong>ACE</strong>s must use asynchronous sessions to communicate with the<br />
OMS, because they cannot block. For more information synchronous and asynchronous<br />
OMS sessions, see the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
The thread you create for synchronous communication in a task must poll for crosscall<br />
events using ix_cap_loop or ix_cap_poll.<br />
Crosscalls and<br />
Library <strong>ACE</strong>s<br />
Predefined library and system <strong>ACE</strong>s supplied by <strong>Intel</strong> ® typically act as crosscall<br />
servers. They export their crosscall interface definitions, as well as the generated stub<br />
files resulting from the compilation. You can regenerate the stub files from the original<br />
interfaces if necessary.<br />
Any <strong>ACE</strong> or task in your application can act as a crosscall client to a library or system<br />
<strong>ACE</strong> by including the generated stub code, initializing the crosscall interfaces, and<br />
calling the stub functions.<br />
You must not modify the generated stub code that is provided. If an interface<br />
includes deferred operations, you must define callback handlers based on the<br />
provided templates. These handlers are part <strong>of</strong> your application and are not<br />
supported by <strong>Intel</strong>.<br />
124 Communication Within an Application<br />
Revision 3.3, August 2001
Initializing and Terminating Interfaces<br />
Initializing and Terminating Interfaces<br />
The client and server programs must each provide code to initialize and terminate its<br />
interaction with the OMS crosscall mechanism. Initialization makes the client and<br />
server programs ready to communicate through the OMS. The client can make stub<br />
calls successfully only after initialization is complete.<br />
For each interface defined in the <strong>IXA</strong> IDL file, the compiler generates client initialization<br />
and termination functions in the stub file, and server initialization and termination<br />
functions in the crosscall file.<br />
Initializing the<br />
Client<br />
The client initialization function has a generated name in the form<br />
stub_module_interface_init. It has the following prototype:<br />
ix_error stub_module_interface_init<br />
(ix_base_t *ifbasep,<br />
ix_cap *clientcap);<br />
Argument<br />
ifbasep<br />
clientcap<br />
Description<br />
A pointer to the crosscall base structure (token) for this interface. For<br />
each interface that the client will use, the initialization code must create<br />
a token <strong>of</strong> type ix_base_t, and pass it to the interface initialization<br />
function.<br />
A pointer to the CAP for this call client, the structure used for OMS<br />
communication. To provide this argument, convert the <strong>ACE</strong> or task<br />
structure for the client to an ix_cap using the ASL functions<br />
ix_ace_to_cap and ix_task_to_cap.<br />
The interface base structure, or token, keeps all required information for the specific<br />
interface, until the application releases it after calling the interface’s termination function.<br />
The ix_base_t structure must not reside in read-only memory. Before creating<br />
it, the application should initialize the memory for the structure to zero. For example:<br />
memset(basep,0,size<strong>of</strong>(ix_base_t));<br />
The termination function for the interface has the following signature:<br />
extern ix_error stub_module_interface_fini (ix_base_t* basep);<br />
Client<br />
Initialization<br />
Example<br />
The following example shows how to initialize and terminate a task client for the<br />
ixa_c_Example1 interface.<br />
1. Create and initialize a task, and extract the CAP structure used for OMS communication.<br />
Several interfaces can use the same CAP.<br />
ix_error err = 0;<br />
static ix_task* pTask = NULL;<br />
static ix_cap* pCap = 0;<br />
pTask = malloc(size<strong>of</strong>(ix_task));<br />
Communication Within an Application 125<br />
Revision 3.3, August 2001
Initializing and Terminating Interfaces<br />
if (pTask == NULL)<br />
{<br />
err = ix_error_new(0,0,err, "%s - ix_task structure allocation<br />
failed!\n",localFunctionName);<br />
goto err_label1;<br />
};<br />
err = ix_task_init (pTask,<br />
"debugClientCap");<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err, "%s - ix_task_init call<br />
failed!\n",localFunctionName);<br />
goto err_label1;<br />
};<br />
err = ix_task_to_cap (pTask,<br />
&pCap);<br />
if (err || !pCap)<br />
{<br />
err = ix_error_new(0,0,err, "%s - ix_task_to_cap call<br />
failed!\n",localFunctionName);<br />
goto err_label1;<br />
};<br />
2. For two-way operations declared in the IDL interface, create and start a worker<br />
thread:<br />
/* Thread run function */<br />
static ix_error idl_thread_run(void* cookie, void** dummy)<br />
{<br />
ix_error err = 0;<br />
(void)dummy;<br />
ix_error_init(16, 128);<br />
fprintf(stderr,"Communication thread started!\n");<br />
err = ix_cap_loop((ix_cap*)cookie);<br />
if((err != 0) && !ix_error_is(err, 0, IX_ERROR_STOP))<br />
ix_error_dump(stderr,err);<br />
}<br />
return err;<br />
{<br />
ix_ossl_thread_t aThread;<br />
//utility fn provided w/<strong>SDK</strong><br />
err = ix_ossl_create_thread (&aThread,idl_thread_run,<br />
(void*) pCap);<br />
if (err)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_ossl_create_thread call failed!\n",<br />
localFunctionName);<br />
};<br />
}<br />
126 Communication Within an Application<br />
Revision 3.3, August 2001
Initializing and Terminating Interfaces<br />
3. Create and initialize a token for each interface:<br />
static const char localFunctionName[] =<br />
"initInterface"; ix_error err = 0;<br />
ix_base_t* pToken = 0;<br />
pToken = malloc(size<strong>of</strong>(ix_base_t));<br />
if(pToken == 0)<br />
return ix_error_new(0,0,err,<br />
"%s :: Token allocation failed!\n",<br />
localFunctionName);<br />
memset(pToken,0,size<strong>of</strong>(ix_base_t));<br />
Use memset to initialize the token before passing it to the interface initialization<br />
function.<br />
Create and initialize a different ix_base_t token for each interface the client will<br />
use. Do not use the same token for initializing different interfaces.<br />
4. Initialize the interface by calling its generated initialization function.<br />
err = stub_ixa_c_Example1_init (pToken, pCap);<br />
if(err)<br />
{<br />
free(pToken);<br />
return ix_error_new(0,0,err,<br />
"%s :: Token initialization failed!\n",<br />
localFunctionName);<br />
}<br />
5. If the client defines callback functions for handling the responses to deferred calls,<br />
update the callback function vector table to point to the function implementations.<br />
See “Initializing Function Pointers” on page 130.<br />
6. Connect to the server.<br />
static const char localFunctionName[] =<br />
"connectClient";<br />
static const char serverName[] = "aServer";<br />
ix_error err = 0;<br />
err = ix_oms_connect(pToken, serverName);<br />
if (err)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_oms_connect failed!\n",localFunctionName);<br />
};<br />
err = ix_oms_wait_connected(pToken);<br />
if (err)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_oms_wait_connected failed!\n",<br />
localFunctionName);<br />
};<br />
Communication Within an Application 127<br />
Revision 3.3, August 2001
Initializing and Terminating Interfaces<br />
If the server is already running, the connection completes immediately; otherwise<br />
the application either waits for a server to come up or times out. The call to<br />
ix_oms_wait_connected blocks. If your client is an <strong>ACE</strong>, or cannot block for any<br />
other reason, you must connect asynchronously (see the <strong>IXA</strong> <strong>SDK</strong> Reference for<br />
details).<br />
Connect to the server separately for each client interface.<br />
7. After all interface are initialized and the connection for each is completed, the<br />
client can make calls to stub functions in the interfaces. See “Invoking Crosscall<br />
Functions” on page 130.<br />
8. When the client is finished making calls to an interface, disconnect from the server<br />
connection for that interface.<br />
static const char localFunctionName[] =<br />
"disconnectClient";<br />
ix_error err = 0;<br />
err = ix_oms_disconnect(pToken);<br />
if (err)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_oms_disconnect failed!\n",<br />
localFunctionName);<br />
};<br />
err = ix_oms_wait_disconnected(pToken);<br />
if (err)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_oms_wait_disconnected failed!\n",<br />
localFunctionName);<br />
};<br />
return err;<br />
9. Call the termination function for that interface, then free its token.<br />
ix_error err = 0;<br />
err = stub_ixa_c_Example1_fini(pToken);<br />
free(pToken);<br />
10. Shut down the thread and terminate the task.<br />
err = ix_task_fini(pTask);<br />
Initializing the<br />
Server<br />
The process is similar for the server. The compiler generates server initialization and<br />
termination functions in the skeleton file. The server initialization function has a<br />
generated name in the form sk_module_interface_init. It has the following prototype:<br />
ix_error sk_module_interface_init<br />
(ix_base_t *ifbasep,<br />
ix_cap *servercap);<br />
128 Communication Within an Application<br />
Revision 3.3, August 2001
Initializing and Terminating Interfaces<br />
Argument<br />
ifbase<br />
servercap<br />
Description<br />
A pointer to the crosscall base structure for this interface.<br />
A pointer to the CAP for this call server. To obtain the CAP, use one <strong>of</strong><br />
the ASL functions ix_ace_to_cap or ix_task_to_cap.<br />
The termination function for the interface has the following signature:<br />
extern ix_error sk_module_interface_fini (ix_base_t* basep);<br />
Server<br />
Initialization<br />
Example<br />
The following example shows how to initialize and terminate an <strong>ACE</strong> server for the<br />
ixa_c_Example1 interface:<br />
1. As part <strong>of</strong> the <strong>ACE</strong> initialization (ix_ace_init), extract the CAP structure.<br />
...<br />
ix_cap* pCap=0; //allocate a CAP variable<br />
...<br />
err = ix_ace_to_cap (pAce, &pCap); //extract the CAP<br />
if (err || !pCap)<br />
{<br />
err = ix_error_new(0,0,err, "%s - ix_task_to_cap call<br />
failed!\n",localFunctionName);<br />
goto err_label1;<br />
};<br />
2. Create and initialize a token for each interface:<br />
static const char localFunctionName[] =<br />
"initInterface"; ix_error err = 0;<br />
ix_base_t* pToken = 0;<br />
pToken = malloc(size<strong>of</strong>(ix_base_t));<br />
if(pToken == 0)<br />
return ix_error_new(0,0,err,<br />
"%s :: Token allocation failed!\n",<br />
localFunctionName);<br />
memset(pToken,0,size<strong>of</strong>(ix_base_t));<br />
Use memset to initialize the token before passing it to the interface initialization<br />
function. Create and initialize a different ix_base_t token for each interface. Do<br />
not use the same token for initializing different interfaces.<br />
3. Initialize each interface by calling its generated initialization function, passing the<br />
token and the extracted CAP.<br />
err = sk_ixa_c_Example1_init (pToken, pCap);<br />
if(err)<br />
{<br />
free(pToken);<br />
return ix_error_new(0,0,err,<br />
"%s :: Token initialization failed!\n",<br />
Communication Within an Application 129<br />
Revision 3.3, August 2001
Invoking Crosscall Functions<br />
}<br />
localFunctionName);<br />
4. Reset the crosscall function vector to point to the function implementations,<br />
rather than the templates. See “Initializing Function Pointers” on page 130.<br />
5. During shutdown, call the termination function for each interface, then free its<br />
token.<br />
ix_error err = 0;<br />
err = sk_ixa_c_Example1_fini(pToken);<br />
free(pToken);<br />
Initializing<br />
Function<br />
Pointers<br />
The <strong>IXA</strong> IDL compiler creates a vector table (VMT) that the generated crosscall infrastructure<br />
uses to access the invocation functions. Initially, this table points to the<br />
generated crosscall function templates. The skeleton file defines an accessor function<br />
for the VMT, which you use to change the vector table to point to your function<br />
implementations, which you base on the generated templates.<br />
The accessor function for the crosscall VMT has the following prototype:<br />
extern ix_error getCCVMT_interface<br />
(ix_base_t<br />
*basep,<br />
CC_VMT_interface **pInterfaceCCVMT);<br />
The initialization code for the server must use this accessor to change each crosscall<br />
function pointer. For example:<br />
getCCVMT_MyInterface (pToken, &pCCVMT);<br />
pCCVMT->_pCC_Int1 _op1 = My_Int1_op1;<br />
Similarly, there is a VMT that the client uses to access any callback function for<br />
deferred operations. The stub file defines an accessor function for this VMT that the<br />
client must use to point to the callback function implementations.<br />
The accessor function for the callback VMT has the following prototype:<br />
extern ix_error getCBVMT_interface<br />
(ix_base_t<br />
*basep,<br />
CB_VMT_interface **pInterfaceCBVMT);<br />
The initialization code for the client must use this accessor to change each callback<br />
function. For example:<br />
getCBVMT_MyInterface (pToken, &pCBVMT);<br />
pCBVMT->_pCB_Int1 _cb1 = My_Int1_cb1;<br />
Invoking Crosscall Functions<br />
A call client invokes crosscall functions remotely, using the generated call stub. The<br />
stub has a generated name in the following form:<br />
130 Communication Within an Application<br />
Revision 3.3, August 2001
Invoking Crosscall Functions<br />
ix_error stub_module_interface_callfn<br />
(ix_base_t ifbase,<br />
callargs...)<br />
Each stub function takes as its first argument the interface token (ix_base_t) that the<br />
client defined and initialized for the interface in which the call is defined. This structure<br />
allows the OMS to coordinate the calling operation.<br />
The remaining arguments <strong>of</strong> the stub function are the input arguments defined for<br />
the crosscall, and, in the case <strong>of</strong> a two-way call, the locations <strong>of</strong> variables in which to<br />
store the values <strong>of</strong> any output arguments.<br />
Opening a<br />
Crosscall<br />
Connection<br />
Before you can make any calls, the client must initialize each interface (as described<br />
in “Initializing and Terminating Interfaces” on page 125) and open an OMS connection<br />
to the call server. Because the connection operation takes some time, the client<br />
must make sure that the connection has been established before making calls. The<br />
OMS supplies a number <strong>of</strong> global functions to accomplish this in various ways.<br />
When the call client is an external program, you can open the connection with the<br />
function ix_oms_connect, then block and wait for the connection to complete, using<br />
the function ix_oms_wait_connected.<br />
An <strong>ACE</strong> acting as a call client cannot block, so it cannot wait for the connection to<br />
complete before continuing execution. However, before the client <strong>ACE</strong> can make any<br />
calls, it must make sure that the connection is open. There are two possible ways to<br />
do this:<br />
l<br />
l<br />
Open the connection with the asynchronous function ix_oms_connect_cb, than<br />
wait until the callback is executed before making any calls.<br />
Open the connection with the function ix_oms_connect, which provides no<br />
response, then use the function ix_oms_is_connected to check that the connection<br />
is open before making any calls.<br />
Remote Call<br />
Example<br />
The following example shows an external call client calling into an <strong>ACE</strong>. The example<br />
initializes the crosscall, then establishes a connection to the call server. Because this is<br />
not an <strong>ACE</strong>, it can block and wait until the connection is complete before making the<br />
calls.<br />
ix_error run_test(ix_cap *capp)<br />
{<br />
ix_error err;<br />
ix_base_t if1; //create crosscall base structure<br />
long count = 0;<br />
long retval;<br />
// initialize crosscall interface<br />
memset(&if1,0,size<strong>of</strong>(ix_base_t)); //zero memory<br />
err = stub_toace_if1_init(&if1, capp);<br />
if(err)<br />
return err;<br />
// establish crosscall connect to server <strong>ACE</strong><br />
Communication Within an Application 131<br />
Revision 3.3, August 2001
Invoking Crosscall Functions<br />
err = ix_oms_connect(&if1, "myace");<br />
if(err)<br />
return err;<br />
// wait for connection to complete before making calls<br />
err = ix_oms_wait_connected(&if1);<br />
if(err)<br />
return err;<br />
printf("CONNECTED!!!");<br />
// make calls<br />
while(1){<br />
err = stub_toace_if1_one_func (&base, count++);<br />
if(err)<br />
return err;<br />
printf("Oneway call sent. count = %ld\n", count);<br />
err = stub_toace_if1_two_func (&base, count++, &retval);<br />
if(err)<br />
return err;<br />
printf("Twoway call sent. count = %ld retval = %ld\n",<br />
count, retval);<br />
err = stub_toace_if1_def_func (&base, count++);<br />
if(err)<br />
return err;<br />
printf("Deferred call sent. count = %ld\n",<br />
count);<br />
132 Communication Within an Application<br />
Revision 3.3, August 2001
Passing Crosscall Arguments<br />
}<br />
sleep(1);<br />
}<br />
Passing Crosscall Arguments<br />
The arguments that you declare for an operation in the interface definition can be<br />
used for input, output, or both, depending on the invocation type <strong>of</strong> the operation. If<br />
the operation is two way or deferred, you can also declare a return type, which is<br />
mapped to an output argument.<br />
The compiler maps the declared arguments to parameters in the generated call, stub,<br />
and callback functions and templates in such a way as to allow the calling program<br />
to pass in needed values and retrieve results. If results are expected, the client generally<br />
needs to allocate storage <strong>of</strong> the correct type and pass the address to the stub function.<br />
In general, when invoking a crosscall with an output (out or inout) parameter, the<br />
caller must pass either the address <strong>of</strong> a variable <strong>of</strong> the proper type or the value <strong>of</strong> a<br />
pointer to that type. The crosscall function being invoked must dereference the<br />
parameter to get to the type. For arrays, the caller must pass the address <strong>of</strong> the first<br />
element <strong>of</strong> the array.<br />
For out parameters <strong>of</strong> types string and wstring, the stub allocates storage for the<br />
output value. The client can use and retain that storage indefinitely. When the value<br />
is no longer needed, the client is responsible for freeing the memory. For all other<br />
types, the client must pass the address <strong>of</strong> a variable <strong>of</strong> the correct type.<br />
l<br />
l<br />
For in parameters, the caller must pass the value <strong>of</strong> the parameter for all <strong>of</strong> the<br />
basic types and enumeration types. For arrays, the caller must pass the address <strong>of</strong><br />
the first element <strong>of</strong> the array. For all other structured types, the caller must pass<br />
the address <strong>of</strong> a variable <strong>of</strong> that type.<br />
For strings, the client must pass a char* or wchar_t*.<br />
For inout parameters, the client must pass the address <strong>of</strong> a variable <strong>of</strong> the correct<br />
type for all <strong>of</strong> the basic types, enumeration types, and structured types. For<br />
strings, the client must pass the address <strong>of</strong> a char*, and for wide strings, the<br />
address <strong>of</strong> a wchar_t*. For arrays, the client must pass the address <strong>of</strong> the first<br />
element <strong>of</strong> the array.<br />
The following table summarizes what a client passes as an argument to a stub function<br />
and receives as a result.<br />
Declared Data Type In Inout Out/Return<br />
short short short* short*<br />
long long long* long*<br />
long long long long long long* long long*<br />
Revision 3.3, August 2001<br />
Communication Within an Application 133
Passing Crosscall Arguments<br />
Declared Data Type In Inout Out/Return<br />
unsigned short unsigned short unsigned short* unsigned short*<br />
unsigned long unsigned long unsigned long* unsigned long*<br />
unsigned long long unsigned long long unsigned long long* unsigned long long*<br />
float float float* float*<br />
double double double* double*<br />
long double long double long double* long double*<br />
boolean boolean boolean * boolean*<br />
char char char* char*<br />
wchar wchar* wchar* wchar*<br />
octet octet octet* octet*<br />
enum enum enum* enum*<br />
struct struct* struct* struct*<br />
union union* union* union*<br />
string char* char** char**<br />
wstring wchar* wchar** wchar**<br />
sequence sequence* sequence* sequence*<br />
array array array array<br />
Client Side<br />
Parameter<br />
Passing<br />
On the client side, follow these guidelines in passing parameters to a stub function:<br />
l<br />
l<br />
l<br />
Ensure that all parameter values are valid and properly initialized.<br />
Ensure that variables exist and are properly initialized before the stub call, then<br />
pass their addresses. The generated initialization function properly initializes all<br />
complex type parameters.<br />
When passing in parameters:<br />
— For all basic types, pass by value.<br />
— For complex types except arrays, pass as const type*.<br />
— For strings, pass as const char* or const wchar_t*.<br />
l<br />
When passing inout and out parameters:<br />
— For all basic types and all complex types except arrays, pass as type*.<br />
134 Communication Within an Application<br />
Revision 3.3, August 2001
Passing Crosscall Arguments<br />
— For arrays, pass the address <strong>of</strong> the first element.<br />
— For inout strings, point to a valid zero-terminated arrays <strong>of</strong> characters.<br />
— For two-way calls, allocate string inout parameters on the heap, and set out<br />
parameters to 0. The generated stub code frees the memory before demarshalling<br />
the response values. The client application is responsible for making a<br />
copy if it needs the value. (For deferred calls, out parameters are not generated<br />
in the stub signature and you do not pass addresses for them to the stub<br />
functions.)<br />
The application is responsible for freeing any memory it has allocated after the stub<br />
call returns, before exiting the scope where the variables have been declared. For all<br />
structured data types, clean up by calling the generated termination function.<br />
l<br />
l<br />
l<br />
l<br />
The termination function frees all valid strings that are contained in complex<br />
structures (except sequences with the _release flag set to 0). To ensure that this<br />
is successful, allocate the strings on the heap.<br />
For inout and out string and wstring parameters, the client must free the<br />
addressed memory. For in parameters, the way you free the memory in the client<br />
depends on how you allocated the memory before passing the parameter to the<br />
stub function.<br />
For two-way calls, the client must make copies <strong>of</strong> any useful inout data because<br />
the variables disappear after the stub function returns.<br />
For deferred calls, do not free the inout and out parameters that the OMS will<br />
pass to the callbacks. Make copies <strong>of</strong> any useful data, as these go out <strong>of</strong> scope after<br />
the callback returns.<br />
What the Stub Function Does to Passed Parameters<br />
l<br />
l<br />
l<br />
The generated stub function does not modify in parameters.<br />
For inout parameters, the stub function overwrites the passed parameters with<br />
the new values. In the case <strong>of</strong> strings or complex types containing strings, the stub<br />
frees the memory to which the parameter points. In case <strong>of</strong> unbounded sequences,<br />
if the received buffer is bigger than the existing one, the stub reallocates memory.<br />
If the sequence has the _release flag set to 0, the stub does not free contained<br />
strings.<br />
For out parameters, the stub function writes the result data at the location<br />
provided by the caller, overwriting any data that is already there.<br />
Server Side<br />
Parameter<br />
Passing<br />
On the server side, the OMS properly initializes all parameters before passing them<br />
to the crosscall function. The application should allocate all strings for the crosscall<br />
on the heap. After the crosscall function returns and the response is sent back, the<br />
OMS performs the cleanup, freeing all strings contained in complex structures except<br />
for those contained in sequences where you set the _release flag to 0.<br />
For inout and out string and wstring parameters, the application must first free<br />
the memory that is passed in, then dynamically allocate memory for return values.<br />
The generated code attempts to free the memory as soon the crosscall function<br />
returns. If the application modifies an incoming string in place, there is no need to<br />
free and allocate memory for the return value.<br />
Communication Within an Application 135<br />
Revision 3.3, August 2001
Passing Crosscall Arguments<br />
Passing<br />
Values in a<br />
One-way Call<br />
To make a one-way call, the client must do the following:<br />
1. Initialize the interface containing the one-way call, using the generated initialization<br />
function.<br />
2. Declare and initialize the in variables.<br />
3. Make the call to the appropriate stub function. The stub function does the<br />
following:<br />
— Marshals the operation ID.<br />
— Marshals all in variables.<br />
— Dispatches the call to OMS.<br />
— Returns.<br />
4. Clean up all the input variables.<br />
On the server side, a demultiplexing mechanism receives the call, demarshals the<br />
operation ID and invokes the proper call function as indicated by the operation ID.<br />
The OMS does the following:<br />
1. Creates and initializes variables for all in parameters.<br />
2. Demarshals all in parameters into the corresponding variables.<br />
3. Calls the application-defined crosscall function.<br />
4. Cleans up the in parameter variables.<br />
Passing<br />
Values in a<br />
Two-way Call<br />
To make a two-way call, the client must do the following:<br />
1. Initialize the interface containing the two-way call, using the generated initialization<br />
function.<br />
2. Declare and initialize the in, inout, and out variables.<br />
3. Make the call to the appropriate stub function. The stub function does the<br />
following:<br />
— Marshals the operation ID.<br />
— Marshals all in and inout variables.<br />
— Dispatches the call to OMS and blocks, waiting for the response.<br />
— Releases all inout variables.<br />
— Demarshals inout and out parameters in the corresponding variables<br />
4. Upon return from the call, process returned values as needed.<br />
5. Clean up all variables.<br />
On the server side, a demultiplexing mechanism receives the call, demarshals the<br />
operation ID and invokes the proper call function as indicated by the operation ID.<br />
The OMS does the following:<br />
1. Creates and initializes variables for all in, inout, and out parameters.<br />
2. Demarshals all in, inout, and out parameters into the corresponding variables.<br />
136 Communication Within an Application<br />
Revision 3.3, August 2001
Passing Crosscall Arguments<br />
3. Calls the application-defined crosscall function, which initializes the inout and<br />
out parameters to the return values.<br />
4. Marshals the inout and out variables.<br />
5. Cleans up all variables.<br />
When the client allocates resources for a stub function variable in a two-way call, it is<br />
responsible for freeing those resources when the application no longer needs the<br />
value.<br />
Passing<br />
Values in a<br />
Deferred Call<br />
To make a deferred call, the client must do the following:<br />
1. Initialize the interface containing the deferred call, using the generated initialization<br />
function.<br />
2. Declare and initialize the in and inout variables.<br />
3. Make the call to the appropriate stub function. The stub function does the<br />
following:<br />
— Marshals the operation ID.<br />
— Marshals all in and inout variables.<br />
— Dispatches the call to OMS.<br />
4. Clean up all variables.<br />
On the server side, a demultiplexing mechanism receives the call, demarshals the<br />
operation ID and invokes the proper call function as indicated by the operation ID.<br />
The OMS does the following:<br />
1. Creates and initializes variables for all in, inout, and out parameters.<br />
2. Demarshals all in, inout, and out parameters into the corresponding variables.<br />
3. Calls the application-defined crosscall function, which initializes the inout and<br />
out parameters to the return values.<br />
4. Marshals the inout and out parameters into the corresponding variables.<br />
5. Invokes the application-defined callback function in the client, passing the<br />
parameters as arguments.<br />
6. Cleans up all variables it has created.<br />
When the callback function has performed the required processing on the returned<br />
values, the client must clean up any variables created for it.<br />
Communication Within an Application 137<br />
Revision 3.3, August 2001
Passing Crosscall Arguments<br />
138 Communication Within an Application<br />
Revision 3.3, August 2001
Chapter 12<br />
Crosscall Example<br />
This chapter provides a demonstration <strong>of</strong> the crosscall mechanism that is used for communication<br />
between s<strong>of</strong>tware objects through the OMS. It contains the following topics:<br />
l “Overview” on page 139<br />
l “Example Interface Definition” on page 140<br />
l “Writing the Crosscall Client” on page 144<br />
l “Writing the Crosscall Server” on page 152<br />
Overview<br />
In this example, the <strong>IXA</strong> IDL specification defines an agreement between a client<br />
process and a server process about certain services that will be executed by the server<br />
on behalf <strong>of</strong> the client. In this case, the service is a simple database <strong>of</strong> person objects<br />
with a name and an age, for which a client can add, modify, or delete entries. The <strong>IXA</strong><br />
IDL compiler maps this definition into OMS-specific calls that perform the required<br />
service. The compiler generates source files for the server and for the client.<br />
l<br />
l<br />
For the server side, the compiler generates the required mechanisms for receiving<br />
the call and the invoking the crosscall function, as well as templates for the crosscall<br />
functions that provide the services. When developing the application, you use<br />
the template to implement the actual call functions. The server must link all<br />
generated files and include their headers, so that it contains all <strong>of</strong> the calling infrastructure,<br />
in addition to the call function definitions.<br />
For the client side, the compiler generates stub functions that the client uses to<br />
make the calls, and provides template callback functions for deferred calls. The<br />
client must link the stub code and include the headers, and also the implementations<br />
<strong>of</strong> the callback functions if there are deferred calls.<br />
Revision 3.3, August 2001<br />
Crosscall Example 139
Example Interface Definition<br />
Example Interface Definition<br />
The following <strong>IXA</strong> IDL code defines the Person crosscall interface, which defines a<br />
data structure to hold information about people (their name and age), and one operation<br />
<strong>of</strong> each type to act on that data:<br />
interface Person<br />
{<br />
struct person_Entry<br />
{<br />
string<br />
name;<br />
unsigned short age;<br />
};<br />
};<br />
oneway void addPerson(in person_Entry aPerson);<br />
unsigned short getAge(in string aName);<br />
deferred boolean deletePerson(in string aName);<br />
Notice that the getAge operation uses the default twoway invocation type.<br />
Rather than declaring inout or out parameters, the two-way and deferred operations<br />
return values, which will be mapped to output parameters during compilation.<br />
Generated<br />
Stub Files<br />
The <strong>IXA</strong> IDL compiler generates the following _stub_c.h file for the Person interface.<br />
The generated code declares initialization and termination functions for the client<br />
side <strong>of</strong> the interface, and stub functions for each operation defined in the interface.<br />
The compiler creates a vector table (VMT) that the generated crosscall infrastructure<br />
uses to access the callback functions for deferred operation. Initially, this table points<br />
to the generated callback function templates. This stub file defines an accessor function<br />
for the VMT, which you use to change the vector table to point to your function<br />
implementations, which you base on the generated templates.<br />
#ifndef _OMS_IDL_C_<strong>IXA</strong>_C_EXAMPLE1_STUB_C_H_<br />
#define _OMS_IDL_C_<strong>IXA</strong>_C_EXAMPLE1_STUB_C_H_<br />
#ifdef __cplusplus<br />
extern "C"<br />
{<br />
#endif /* __cplusplus */<br />
#include "ix/asl.h"<br />
#include "ix/ns.h"<br />
#include "ix/ossl.h"<br />
#include "ix/asl/ixbasecc.h"<br />
/**=================================================<br />
* Start stub declaration <strong>of</strong> interface Person<br />
*================================================*/<br />
140 Crosscall Example<br />
Revision 3.3, August 2001
Example Interface Definition<br />
/* Declare the interface name for Person interface */<br />
extern const char Person_intName[];<br />
/* Declare the local operation names for CC_VMT_Person interface */<br />
/* Declare the name for Person::addPerson operation */<br />
extern const char Person_addPerson_opName[];<br />
/* Declare the name for Person::getAge operation */<br />
extern const char Person_getAge_opName[];<br />
/* Declare the name for Person::deletePerson operation */<br />
extern const char Person_deletePerson_opName[];<br />
/* Client initialization function for Person interface */<br />
extern ix_error stub_Person_init(ix_base_t* basep,<br />
ix_cap *capp);<br />
/* Client finalization function for Person interface */<br />
extern ix_error stub_Person_fini(ix_base_t* basep);<br />
typedef struct<br />
{<br />
char* name;<br />
unsigned short age;<br />
} Person_person_Entry;<br />
/**=================================================<br />
* Helper functions for Person_person_Entry structure<br />
*================================================*/<br />
/* Marshaling function for Person::person_Entry structure */<br />
extern ix_error ix_sds_r_Person_person_Entry (ix_sds aSds, const<br />
Person_person_Entry* val);<br />
/* Demarshaling function for Person::person_Entry structure */<br />
extern ix_error ix_sds_p_Person_person_Entry (ix_sds aSds,<br />
Person_person_Entry* val);<br />
/* Initialization function for Person::person_Entry structure */<br />
extern ix_error init_Person_person_Entry (Person_person_Entry* val);<br />
/* Finalization function for Person::person_Entry structure */<br />
extern ix_error fini_Person_person_Entry (Person_person_Entry* val);<br />
/* Release function for Person::person_Entry structure */<br />
extern ix_error release_Person_person_Entry (Person_person_Entry*<br />
val);<br />
/**=================================================<br />
* End helper functions for Person_person_Entry structure<br />
*================================================*/<br />
Crosscall Example 141<br />
Revision 3.3, August 2001
Example Interface Definition<br />
/* Declare the a cross call function pointer type for<br />
Person::addPerson operation */<br />
typedef ix_error (* Person_addPerson_fptr)(ix_base_t* basep, const<br />
Person_person_Entry* aPerson);<br />
/* Declare the crosscall reference function for Person::addPerson<br />
operation */<br />
extern ix_error stub_Person_addPerson(ix_base_t* basep, const<br />
Person_person_Entry* aPerson);<br />
/* Declare the a cross call function pointer type for Person::getAge<br />
operation */<br />
typedef ix_error (* Person_getAge_fptr)(ix_base_t* basep, const<br />
char* aName, unsigned short* _return_val);<br />
/* Declare the crosscall reference function for Person::getAge<br />
operation */<br />
extern ix_error stub_Person_getAge(ix_base_t* basep, const char*<br />
aName, unsigned short* _return_val);<br />
/* Declare the a cross call function pointer type for<br />
Person::deletePerson operation */<br />
typedef ix_error (* Person_deletePerson_fptr)(ix_base_t* basep,<br />
const char* aName, int* _return_val);<br />
/* Declare the crosscall reference function for Person::deletePerson<br />
operation */<br />
extern ix_error stub_Person_deletePerson(ix_base_t* basep, const<br />
char* aName);<br />
/* Declare the deffered callback function for Person::deletePerson<br />
operation */<br />
extern ix_error deferred_cb_Person_deletePerson (ix_error anError,<br />
void* cookie, ix_sds aSds);<br />
/* Declare the callback function pointer type for<br />
Person::deletePerson operation */<br />
typedef ix_error (* Person_deletePerson_cb_fptr)( ix_base_t* basep,<br />
ix_error anError, int _return_val);<br />
/* Declare the crosscall VMT structure for Person interface */<br />
/**************<br />
** CC_VMT_Person structure holds function pointers<br />
** to implementation functions for all local<br />
** and inherited operations<br />
***************/<br />
typedef struct _CC_VMT_Person<br />
{<br />
Person_addPerson_fptr _pCC_Person_addPerson;<br />
Person_getAge_fptr _pCC_Person_getAge;<br />
Person_deletePerson_fptr _pCC_Person_deletePerson;<br />
} CC_VMT_Person;<br />
/* Declare the callback VMT structure for Person interface */<br />
142 Crosscall Example<br />
Revision 3.3, August 2001
Example Interface Definition<br />
/**************<br />
** CB_VMT_Person structure holds function pointers to callback<br />
** functions for all local and inherited operations<br />
****************/<br />
typedef struct _CB_VMT_Person<br />
{<br />
Person_deletePerson_cb_fptr _pCB_Person_deletePerson;<br />
} CB_VMT_Person;<br />
/* Accessor function for callback VMT */<br />
extern ix_error getCBVMT_Person(ix_base_t* basep,<br />
CB_VMT_Person** pInterfaceCBVMT);<br />
/**=================================================<br />
* End stub declaration <strong>of</strong> interface Person<br />
*================================================*/<br />
#ifdef __cplusplus<br />
}<br />
#endif /* __cplusplus */<br />
#endif /* end define */<br />
Generated<br />
Skeleton Files<br />
The <strong>IXA</strong> IDL compiler generates the following _sk_c.h file for the Person interface,<br />
which the server code includes.<br />
The generated code declares initialization and termination functions for the server<br />
side <strong>of</strong> the interface, and invocation functions for each operation defined in the interface.<br />
The compiler creates a vector table (VMT) that the generated crosscall infrastructure<br />
uses to access the invocation functions. Initially, this table points to the<br />
generated crosscall function templates. The skeleton file defines an accessor function<br />
for the VMT, which you use to change the vector table to point to your function<br />
implementations, which you base on the generated templates.<br />
#ifdef __cplusplus<br />
extern "C"<br />
{<br />
#endif /* __cplusplus */<br />
#include "ixa_c_example1_stub_c.h"<br />
/**=================================================<br />
* Start skeleton declaration <strong>of</strong> interface Person<br />
*================================================*/<br />
/* Server initialization function for Person interface */<br />
extern ix_error sk_Person_init (ix_base_t* basep, ix_cap* capp);<br />
/* Server finalization function for Person interface */<br />
extern ix_error sk_Person_fini (ix_base_t* basep);<br />
/* Accessor function for crosscall VMT */<br />
extern ix_error getCCVMT_Person(ix_base_t* basep,<br />
Crosscall Example 143<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
CC_VMT_Person** pInterfaceCCVMT);<br />
/* Declare the invoke function for Person::addPerson operation */<br />
extern ix_error invoke_Person_addPerson(ix_base_t* basep, ix_sds<br />
anSds, idl_ixa_c_crossCall_fptr pFunc);<br />
/* Declare the invoke function for Person::getAge operation */<br />
extern ix_error invoke_Person_getAge(ix_base_t* basep, ix_sds anSds,<br />
idl_ixa_c_crossCall_fptr pFunc);<br />
/* Declare the invoke function for Person::deletePerson operation */<br />
extern ix_error invoke_Person_deletePerson(ix_base_t* basep, ix_sds<br />
anSds, idl_ixa_c_crossCall_fptr pFunc);<br />
/**=================================================<br />
* End skeleton declaration <strong>of</strong> interface Person<br />
*================================================*/<br />
#ifdef __cplusplus<br />
}<br />
#endif /* __cplusplus */<br />
#endif /* end define */<br />
Writing the Crosscall Client<br />
The client program adds a new person, retrieves the age <strong>of</strong> the same person, then<br />
deletes the entry it has added, using the defined crosscalls. The following code establishes<br />
a connection to the server and initializes the crosscall interface, than calls the<br />
generated stub functions and handles the returned values. Finally, it terminates the<br />
crosscall connection and cleans up allocated space.<br />
This file defines an initialization function, idl_client_init, that takes command<br />
line arguments (argc and argv):<br />
l<br />
l<br />
The first argument is the name <strong>of</strong> the crosscall server to which to connect.<br />
The second argument is command, one <strong>of</strong> the strings ADD, DEL, or AGE.<br />
— "ADD" must be followed by two more arguments, a name and a number for<br />
the age. The program will add the specified person.<br />
— "DEL" or "AGE" must be followed by one more argument, a name. The<br />
program will delete or retrieve the name <strong>of</strong> the specified person.<br />
The initialization also changes the callback pointer for the deferred operation from<br />
the generated template function to the application-defined callback function.<br />
//Crosscall client for Person interface<br />
#include <br />
#include <br />
#include <br />
#include <br />
#include "person_stub_c.h"<br />
#include "person_cb_c.h"<br />
144 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
static ix_task* _p_idl_ixa_c_clientTestTask = 0;<br />
static ix_cap* _p_idl_ixa_c_clientTestCap = 0;<br />
static ix_ossl_thread_t _Thread = 0;<br />
static ix_base_t* pToken = 0;<br />
static int responseReceived = 0;<br />
ix_error our_Person_deletePerson_cb(ix_base_t* basep,<br />
ix_error anError, int _return_int);<br />
static ix_error idl_thread_run(void* cookie, void** dummy)<br />
{<br />
ix_error err = 0;<br />
(void)dummy;<br />
ix_error_init(16, 128);<br />
fprintf(stderr,"Communication thread started!\n");<br />
err = ix_cap_loop((ix_cap*)cookie);<br />
if((err != 0) && !ix_error_is(err, 0, IX_ERROR_STOP))<br />
ix_error_dump(stderr,err);<br />
return err;<br />
}<br />
//Callback function for deferred op, based on generated template<br />
ix_error our_Person_deletePerson_cb (ix_base_t* basep,<br />
ix_error anError, int _return_int)<br />
{<br />
static const char localFunctionName[] =<br />
"our_Person_deletePerson_cb";<br />
ix_error err = 0;<br />
(void)basep;<br />
if(anError)<br />
{<br />
responseReceived = 1;<br />
return anError;<br />
}<br />
if(_return_int >= 0)<br />
fprintf(stderr, "%s - deletePerson operation has been<br />
successful!\n", localFunctionName);<br />
else<br />
fprintf(stderr, "%s - deletePerson operation failed!\n",<br />
localFunctionName);<br />
}<br />
responseReceived = 1;<br />
return err;<br />
static ix_error idl_client_init(int argc, char** argv)<br />
{<br />
static char localFunctionName[]="idl_client_init";<br />
ix_error err = 0;<br />
CB_VMT_Person* pCBVMT = 0;<br />
int aResult = 0;<br />
ix_error threadError = 0;<br />
Crosscall Example 145<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
void* context;<br />
if (argc
Writing the Crosscall Client<br />
}<br />
goto err_label1;<br />
memset(pToken,0,size<strong>of</strong>(ix_base_t));//init token memory<br />
//call generated interface initialization function<br />
err = stub_Person_init (pToken, _p_idl_ixa_c_clientTestCap);<br />
if(err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s :: stub_Person_init failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
}<br />
err = ix_oms_connect(pToken, argv[1]);//connect to server<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - ix_oms_connect failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
err = ix_oms_wait_connected(pToken);<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - ix_oms_wait_connected failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
//Specify the externally defined callback function<br />
err = getCBVMT_Person(pToken, &pCBVMT);<br />
if(err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
" getCBVMT_Person function failed!\n");<br />
goto err_label1;<br />
}<br />
pCBVMT->_pCB_Person_deletePerson =<br />
our_Person_deletePerson_cb;<br />
return err;<br />
err_label1:<br />
/* Shutdown */<br />
/* signal the cap to clean-up and exit */<br />
err = ix_cap_shutdown(_p_idl_ixa_c_clientTestCap, &aResult);<br />
if(err || aResult)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - ix_cap_shutdown failed!\n",<br />
localFunctionName);<br />
Crosscall Example 147<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
};<br />
err = ix_ossl_wait_for_thread(_Thread, &threadError,<br />
&context);<br />
ix_ossl_kill_thread(_Thread);<br />
if(_p_idl_ixa_c_clientTestTask!=0)<br />
{<br />
ix_error err1 = 0;<br />
err1 = ix_task_fini(_p_idl_ixa_c_clientTestTask);<br />
if (err1)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_task_fini failed!\n",<br />
localFunctionName);<br />
};<br />
free(_p_idl_ixa_c_clientTestTask);<br />
_p_idl_ixa_c_clientTestTask = 0;<br />
_p_idl_ixa_c_clientTestCap = 0;<br />
}<br />
if(pToken!=0)<br />
{<br />
free(pToken);<br />
pToken = 0;<br />
}<br />
}<br />
return err;<br />
static ix_error idl_client_fini(void) //clean up<br />
{<br />
static char localFunctionName[]="idl_client_fini";<br />
ix_error err = 0;<br />
int aResult = 0;<br />
ix_error threadError = 0;<br />
void* context;<br />
err = ix_oms_disconnect(pToken);//disconnect from server<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - ix_oms_disconnect failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
}<br />
err = ix_oms_wait_disconnected(pToken);<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - ix_oms_wait_disconnected failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
}<br />
148 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
err = stub_Person_fini (pToken);// interface termination fn<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - stub_Person_fini failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
}<br />
err_label1:<br />
/* Shutdown */<br />
/* signal the cap to clean-up and exit */<br />
err = ix_cap_shutdown(_p_idl_ixa_c_clientTestCap, &aResult);<br />
if(err || aResult)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - ix_cap_shutdown failed!\n",<br />
localFunctionName);<br />
goto thread_shutdown;<br />
};<br />
err = ix_ossl_wait_for_thread(_Thread, &threadError,<br />
&context);<br />
thread_shutdown:<br />
ix_ossl_kill_thread(_Thread);<br />
if(_p_idl_ixa_c_clientTestTask!=0)<br />
{<br />
ix_error err1 = 0;<br />
err1 = ix_task_fini(_p_idl_ixa_c_clientTestTask);<br />
if (err1)<br />
{<br />
return ix_error_new(0,0,err,<br />
"%s - ix_task_fini failed!\n",<br />
localFunctionName);<br />
};<br />
free(_p_idl_ixa_c_clientTestTask);<br />
};<br />
}<br />
return err;<br />
static ix_error addPerson(const char* aName,<br />
unsigned short anAge)<br />
{<br />
static char localFunctionName[]="addPerson";<br />
ix_error err = 0;<br />
Person_person_Entry anEntry;<br />
err = init_Person_person_Entry(&anEntry);<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - init_Person_person_Entry failed!\n",<br />
Crosscall Example 149<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
anEntry.name = strdup(aName);<br />
anEntry.age = anAge;<br />
//call generated stub function<br />
err = stub_Person_addPerson(pToken,&anEntry);<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - stub_Person_addPerson failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
fprintf(stderr, "%s added to the database!\n",<br />
aName);<br />
err_label1:<br />
{<br />
ix_error err1 = 0;<br />
err1 = fini_Person_person_Entry(&anEntry);<br />
if (err1)<br />
{<br />
err = ix_error_new(0,0,err1,<br />
"%s - fini_Person_person_Entry failed!\n",<br />
localFunctionName);<br />
}<br />
}<br />
return err;<br />
}<br />
static ix_error getAge (const char* aName,<br />
unsigned short* anAge)<br />
{<br />
static char localFunctionName[]="getAge";<br />
ix_error err = 0;<br />
//call generated stub function<br />
err = stub_Person_getAge (pToken, aName, anAge);<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - stub_Person_getAge failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
}<br />
if(*anAge == 0)<br />
fprintf(stderr, "%s is not in the database!\n",aName);<br />
else<br />
fprintf(stderr, "%s is %hu years old!\n",aName, *anAge);<br />
150 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Client<br />
err_label1:<br />
}<br />
return err;<br />
static ix_error deletePerson(const char* aName)<br />
{<br />
static char localFunctionName[]="deletePerson";<br />
ix_error err = 0;<br />
//call generated stub function<br />
err = stub_Person_deletePerson(pToken,aName);<br />
if (err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - stub_Person_deletePerson failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
}<br />
/* Wait to receive the callback response */<br />
while(!responseReceived)<br />
{<br />
sleep(1);<br />
}<br />
err_label1:<br />
return err;<br />
}<br />
static void idl_client_cleanup(ix_error anError)<br />
{<br />
if (anError)<br />
ix_error_dump(stderr,anError);<br />
ix_error_fini();<br />
}<br />
int main(int argc, char** argv)<br />
{<br />
int exitStatus = 0;<br />
ix_error err = 0;<br />
ix_error_init(16, 128);<br />
err = idl_client_init(argc, argv);<br />
if (err)<br />
{<br />
exitStatus = -1;<br />
goto err_label_1;<br />
}<br />
if(strcmp(argv[2],"ADD") == 0)<br />
{<br />
unsigned short age = 1;<br />
if(argc>4)<br />
Crosscall Example 151<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
age = atoi(argv[4]);<br />
err = addPerson(argv[3],age);<br />
if (err)<br />
{<br />
exitStatus = -2;<br />
goto err_label_1;<br />
};<br />
}<br />
else if(strcmp(argv[2],"DEL") == 0)<br />
{<br />
err = deletePerson(argv[3]);<br />
if (err)<br />
{<br />
exitStatus = -2;<br />
goto err_label_1;<br />
}<br />
}<br />
else if(strcmp(argv[2],"AGE") == 0)<br />
{<br />
unsigned short age;<br />
err = getAge(argv[3],&age);<br />
if (err)<br />
{<br />
exitStatus = -2;<br />
goto err_label_1;<br />
}<br />
}<br />
else<br />
{<br />
fprintf(stderr, "Invalid command!\n");<br />
exitStatus = -2;<br />
goto err_label_1;<br />
}<br />
err_label_1:<br />
err = idl_client_fini();<br />
if (err)<br />
{<br />
exitStatus = -3;<br />
idl_client_cleanup(err);<br />
}<br />
idl_client_cleanup(err);<br />
}<br />
return exitStatus;<br />
Writing the Crosscall Server<br />
The crosscall server implements the crosscall operations, basing them on the template<br />
functions provided by the <strong>IXA</strong> IDL compiler. In this example, the server is an <strong>ACE</strong>,<br />
so it also defines the standard <strong>ACE</strong> initialization and termination functions, ix_init<br />
and ix_fini.<br />
152 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
This example creates a database <strong>of</strong> persons, building a double linked list (sorted by<br />
name) in which to keep all the entries received from clients. It implements the three<br />
operations by adding the new entries to the list, deleting them or getting the person’s<br />
age if it is in the list.<br />
It then uses the generated VMT accessor to change the vector table to point to the<br />
correct implementation functions (rather than the default, the generated template<br />
functions). Using this technique, different servers that implement the same interface<br />
in the same process can have different behavior. You could also change the behavior<br />
at run time, based on an external trigger, by changing the vector table to point to<br />
different function implementations.<br />
The server code uses the generated initialization function from the<br />
skeleton to initialize the server side <strong>of</strong> the crosscall connection,<br />
and uses the generated termination function to terminate the<br />
connection and free resources.<br />
#include <br />
#include <br />
#include <br />
#include "person_sk_c.h"<br />
#include "person_cc_c.h"<br />
int addPersonEntry(const char* name, unsigned short age);<br />
int getPersonsAge(const char* name,unsigned short* pAge);<br />
int deletePersonEntry(const char* name);<br />
ix_error our_Person_addPerson(ix_base_t* basep,<br />
const Person_person_Entry* aPerson);<br />
ix_error our_Person_getAge(ix_base_t* basep, const char* aName,<br />
unsigned short* _return_val);<br />
ix_error our_Person_deletePerson(ix_base_t* basep,<br />
const char* aName, int* _return_val);<br />
int removeEntries(void);<br />
typedef struct _PersonEntry PersonEntry;<br />
/***********************************************************<br />
** Data structure and helper functions for manipulating it<br />
************************************************************/<br />
struct _PersonEntry<br />
{<br />
const char* name;<br />
unsigned short age;<br />
PersonEntry* next;<br />
PersonEntry* prev;<br />
};<br />
static PersonEntry* _personList = 0;<br />
int addPersonEntry(const char* name, unsigned short age)<br />
{<br />
PersonEntry* pEntry = _personList;<br />
PersonEntry* pPrevEntry = 0;<br />
PersonEntry* pNewEntry = 0;<br />
int res = 0;<br />
Crosscall Example 153<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
}<br />
int pos;<br />
for(pos = 0; pEntry != 0; pEntry = pEntry->next, pos++)<br />
{<br />
res = strcmp(pEntry->name,name);<br />
if(res == 0)<br />
return -1;<br />
else if(res < 0)<br />
{<br />
pPrevEntry = pEntry;<br />
continue;<br />
}<br />
else<br />
break;<br />
}<br />
pNewEntry = malloc(size<strong>of</strong>(PersonEntry));<br />
if(pNewEntry == 0)<br />
return -2;<br />
memset(pNewEntry,0,size<strong>of</strong>(PersonEntry));<br />
pNewEntry->name = strdup(name);<br />
pNewEntry->age = age;<br />
if(pos == 0)<br />
{<br />
pNewEntry->next = _personList;<br />
if(_personList != 0)<br />
_personList->prev = pNewEntry;<br />
_personList = pNewEntry;<br />
}<br />
else<br />
{<br />
if(pEntry == 0)<br />
{<br />
pNewEntry->prev = pPrevEntry;<br />
pPrevEntry->next = pNewEntry;<br />
}<br />
else<br />
{<br />
pNewEntry->next = pEntry;<br />
pNewEntry->prev = pEntry->prev;<br />
pEntry->prev = pNewEntry;<br />
if(pNewEntry->prev != 0)<br />
pNewEntry->prev->next = pNewEntry;<br />
}<br />
}<br />
return pos;<br />
int getPersonsAge(const char* name,unsigned short* pAge)<br />
{<br />
PersonEntry* pEntry = _personList;<br />
int pos;<br />
int res;<br />
*pAge = 0;<br />
for(pos = 0; pEntry != 0; pEntry = pEntry->next, pos++)<br />
{<br />
res = strcmp(pEntry->name,name);<br />
154 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
}<br />
if(res == 0)<br />
{<br />
*pAge = pEntry->age;<br />
return pos;<br />
}<br />
else if(res > 0)<br />
return -1;<br />
};<br />
return -1;<br />
int deletePersonEntry(const char* name)<br />
{<br />
PersonEntry* pEntry = _personList;<br />
int res = 0;<br />
int pos;<br />
for(pos = 0; pEntry != 0; pEntry = pEntry->next, pos++)<br />
{<br />
res = strcmp(pEntry->name,name);<br />
if(res == 0)<br />
{<br />
if(pEntry->prev != 0)<br />
pEntry->prev->next = pEntry->next;<br />
else<br />
_personList = pEntry->next;<br />
if(pEntry->next != 0)<br />
pEntry->next->prev = pEntry->prev;<br />
free(pEntry);<br />
return pos;<br />
}<br />
else if(res < 0)<br />
continue;<br />
else<br />
break;<br />
};<br />
return -1;<br />
}<br />
int removeEntries()<br />
{<br />
PersonEntry* pEntry = _personList;<br />
for(; _personList != 0; pEntry = _personList)<br />
{<br />
_personList = _personList->next;<br />
free(pEntry);<br />
};<br />
return 0;<br />
}<br />
static ix_base_t* pToken = 0;<br />
/************************************<br />
** Definition <strong>of</strong> crosscall template function for<br />
** Person::addPerson operation<br />
**************************************/<br />
Crosscall Example 155<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
ix_error our_Person_addPerson(ix_base_t* basep,<br />
const Person_person_Entry* aPerson)<br />
{<br />
static const char localFunctionName[] =<br />
"our_Person_addPerson";<br />
ix_error err = 0;<br />
(void) basep;<br />
if(addPersonEntry(aPerson->name,aPerson->age) < 0)<br />
fprintf(stderr, "%s - addPersonEntry failed!\n",<br />
localFunctionName);<br />
}<br />
return err;<br />
/************************************<br />
** Definition <strong>of</strong> crosscall template function for<br />
** Person::getAge operation<br />
***************************************/<br />
ix_error our_Person_getAge (ix_base_t* basep,<br />
const char* aName,<br />
unsigned short* _return_val)<br />
{<br />
static const char localFunctionName[] = "our_Person_getAge";<br />
ix_error err = 0;<br />
(void) basep;<br />
if(getPersonsAge(aName, _return_val) < 0)<br />
fprintf(stderr, "%s - getPersonsAge failed!\n",<br />
localFunctionName);<br />
}<br />
return err;<br />
/************************************<br />
** Definition <strong>of</strong> crosscall template function for<br />
** Person::deletePerson operation<br />
***********************************/<br />
ix_error our_Person_deletePerson(ix_base_t* basep,<br />
const char* aName,<br />
int* _return_val)<br />
{<br />
static const char localFunctionName[] =<br />
"Person_deletePerson";<br />
ix_error err = 0;<br />
(void) basep;<br />
*_return_val = deletePersonEntry(aName);<br />
if(*_return_val < 0)<br />
fprintf(stderr, "%s - deletePersonEntry failed!\n",<br />
localFunctionName);<br />
return err;<br />
156 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
}<br />
/************************************<br />
** <strong>ACE</strong> initialization<br />
***********************************/<br />
ix_error ix_init(int argc, char** argv, ix_ace** acepp)<br />
{<br />
static char localFunctionName[] = "ix_init";<br />
ix_error err = 0;<br />
ix_ace* pAce = 0;<br />
ix_cap* capp = 0;<br />
CC_VMT_Person* pCCVMT = 0;<br />
if (argc
Writing the Crosscall Server<br />
/* Initialize the token for the Person interface */<br />
err = sk_Person_init (pToken, capp);<br />
if(err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s - Token initialization failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
/* Retrieve the cross call VMT */<br />
err = getCCVMT_Person(pToken, &pCCVMT);<br />
if(err)<br />
{<br />
err = ix_error_new(0,0,err,<br />
"%s :: getCCVMT_Person failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
/* Point crosscall vectors to implemented functions */<br />
pCCVMT->_pCC_Person_addPerson = our_Person_addPerson;<br />
pCCVMT->_pCC_Person_getAge = our_Person_getAge;<br />
pCCVMT->_pCC_Person_deletePerson = our_Person_deletePerson;<br />
*acepp = pAce;<br />
fprintf(stderr,"%s: ace communication is initialized!\n",<br />
localFunctionName);<br />
return err;<br />
err_label1:<br />
if(pAce != 0)<br />
{<br />
/* Finalize the ix_ace structure*/<br />
err = ix_ace_fini(pAce);<br />
if (err)<br />
{<br />
err = ix_error_new(IX_ERROR_LEVEL_LOCAL,<br />
IX_ERROR_NULL, err,<br />
"%s: ix_ace_fini failed!\n", localFunctionName);<br />
};<br />
}<br />
free(pAce);<br />
pAce = 0;<br />
};<br />
if(pToken != 0)<br />
{<br />
free(pToken);<br />
pToken = 0;<br />
};<br />
return err;<br />
158 Crosscall Example<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
// <strong>ACE</strong> termination<br />
ix_error ix_fini(int argc, char** argv, ix_ace* pAce)<br />
{<br />
static char localFunctionName[]="ix_fini";<br />
ix_error err = 0;<br />
(void) argc;<br />
(void) argv;<br />
err = sk_Person_fini (pToken);<br />
if (err)<br />
{<br />
err = ix_error_new(0, 0, err,<br />
"%s: Token finalization failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
/* Cleanup the _personList */<br />
removeEntries();<br />
err_label1:<br />
/* Free the ix_ace structure */<br />
if (pAce != 0)<br />
{<br />
/* Finalize the ix_ace structure*/<br />
err = ix_ace_fini(pAce);<br />
if (err)<br />
{<br />
err = ix_error_new(IX_ERROR_LEVEL_LOCAL,<br />
IX_ERROR_NULL, err,<br />
"%s: ix_ace_fini failed!\n",<br />
localFunctionName);<br />
};<br />
free(pAce);<br />
}<br />
free(pAce);<br />
/* Free the token structure */<br />
if(pToken != 0)<br />
free(pToken);<br />
}<br />
fprintf(stderr, "%s: ix_fini called. Cleaned up!\n",<br />
localFunctionName);<br />
return err;<br />
Terminating<br />
the Server<br />
The following code defines a clean termination for the interface in the server.<br />
static char localFunctionName[]="ix_fini";<br />
ix_error err = 0;<br />
(void) argc;<br />
(void) argv;<br />
Crosscall Example 159<br />
Revision 3.3, August 2001
Writing the Crosscall Server<br />
/* Call the generated termination function */<br />
err = sk_Person_fini (pToken);<br />
if (err)<br />
{<br />
err = ix_error_new(0, 0, err,<br />
"%s: Token finalization failed!\n",<br />
localFunctionName);<br />
goto err_label1;<br />
};<br />
/* Clean up the _personList */<br />
removeEntries();<br />
err_label1:<br />
/* Free the ix_ace structure */<br />
if (pAce != 0)<br />
{<br />
/* Terminate the <strong>ACE</strong> */<br />
err = ix_ace_fini(pAce);<br />
if (err)<br />
{<br />
err = ix_error_new(IX_ERROR_LEVEL_LOCAL,<br />
IX_ERROR_NULL, err,<br />
"%s: ix_ace_fini failed!\n",<br />
localFunctionName);<br />
};<br />
free(pAce);<br />
}<br />
/* Free the token structure */<br />
if(pToken != 0)<br />
free(pToken);<br />
fprintf(stderr, "%s: ix_fini called. Cleaned up!\n",<br />
localFunctionName);<br />
return err;<br />
160 Crosscall Example<br />
Revision 3.3, August 2001
Chapter 13<br />
Using Sets <strong>of</strong> Data to Classify Packets<br />
This chapter describes sets and searches, which you can use to classify packets based<br />
on their contents; that is, the values <strong>of</strong> fields. Sets are an efficient way to track a large<br />
number <strong>of</strong> classes <strong>of</strong> packets.<br />
This chapter contains the following topics:<br />
l “Overview <strong>of</strong> Sets and Searches” on page 161<br />
l “When to Use Sets” on page 162<br />
l “Defining Sets and Searches” on page 162<br />
l “How to Use Sets and Searches” on page 167<br />
Overview <strong>of</strong> Sets and Searches<br />
You can define data tables called sets that associate any arbitrary application-defined<br />
data with packets. For each set, you define one or more named searches that determine<br />
whether the current packet has a matching element in the set, based on the values <strong>of</strong><br />
specified fields.<br />
A set is a collection <strong>of</strong> elements where each element has a header <strong>of</strong> one or more keys,<br />
and contains a pointer to any arbitrary data that you define. A search matches the key<br />
values in the header with the values <strong>of</strong> specific fields in an incoming packet. When<br />
all the values match, you can take an action with regard to the matching element; for<br />
example, add to a counter, or access and save another field value in the packet.<br />
When a search does not match any element with the incoming packet, you have the<br />
option <strong>of</strong> adding a new element to the set.<br />
Revision 3.3, August 2001<br />
Using Sets <strong>of</strong> Data to Classify Packets 161
When to Use Sets<br />
When to Use Sets<br />
You use sets to define collections <strong>of</strong> packets that are associated with each other by<br />
virtue <strong>of</strong> their contents. They allow you to keep state information for all packets that<br />
have the same values in specific fields. If you want to form collections on structural<br />
criteria, such as “the set <strong>of</strong> all packets with IP header lengths greater than twenty<br />
bytes,” use a classification predicate rather than a searchable set.<br />
You can take any kind <strong>of</strong> action you want as a result <strong>of</strong> the set classification. For<br />
example, you can count packets going to or from each address, keeping the counters<br />
as set data. You can set targets for packets based on their set membership, add<br />
members to or delete members from the set, or create messages from the packets or<br />
the set data and pass them to other <strong>ACE</strong>s or programs using crosscalls.<br />
You can use sets to associate application data with packets. For example, you can<br />
initialize a set with a list <strong>of</strong> interesting addresses, in order to classify all packets that<br />
come from or go to those addresses. One search might compare the ip.src field <strong>of</strong><br />
packets to the elements <strong>of</strong> the set, to identify any packets that come from one <strong>of</strong> the<br />
addresses. Another search could compare the ip.dest field to the addresses, to identify<br />
packets that are going to them.<br />
You can also use sets to collect new data about packet flow. For example, you can start<br />
with an empty set, and, for each incoming packet that does not already have a<br />
matching set element, create a new set element using its ip.src value, and add it to<br />
the set. When an incoming packet does match, you can increment a counter in the<br />
matching element. In this way, you can keep track <strong>of</strong> the sources <strong>of</strong> all packets coming<br />
through the <strong>ACE</strong>.<br />
Defining Sets and Searches<br />
Use NCL to declare the name and suggest the size <strong>of</strong> a set, and to define the searches<br />
that evaluate set membership. Declare a corresponding C structures for the set in the<br />
<strong>ACE</strong> initialization code. You modify the contents <strong>of</strong> sets using actions. See “Initializing<br />
and Populating Sets” on page 165.<br />
Defining Sets<br />
in NCL<br />
Use the set keyword to declare, name, and define a set in NCL. You provide the<br />
number <strong>of</strong> keys, and suggest a size for the set. For each set, you can define any<br />
number <strong>of</strong> searches, using the search keyword. Each search is associated with one<br />
and only one set, and you name it using the form setname.searchname. You specify<br />
a requires clause in the search. If this Boolean expression succeeds, the search is<br />
executed, and if it fails the search is not executed.<br />
Each search definition specifies the exact number <strong>of</strong> keys that you specified for the<br />
set, and associates each key with a protocol field. When the search is executed, the<br />
<strong>ACE</strong> runtime compares the value <strong>of</strong> the specified protocol field in the current packet<br />
to the value <strong>of</strong> the corresponding key for each element in the set. If all <strong>of</strong> the field<br />
values in the packet match the key values in an element, the search succeeds, and<br />
keeps a pointer to the matching element.<br />
162 Using Sets <strong>of</strong> Data to Classify Packets<br />
Revision 3.3, August 2001
Defining Sets and Searches<br />
You can use a search in a rule or an action, referring to it by the name,<br />
setname.searchname. When you refer to it by name, you are actually referring to<br />
the result <strong>of</strong> the search, which the <strong>ACE</strong> runtime obtains when it parses the search<br />
definition for an incoming packet. A search can have one <strong>of</strong> the following results:<br />
l<br />
l<br />
l<br />
The search did not run because the requirements were not met.<br />
The search ran and found a matching element.<br />
The search ran and did not find a matching element.<br />
Example<br />
The following NCL example defines a set named setIP that has 2 keys, and two<br />
searches in that set that compare each <strong>of</strong> the keys to fields in the IP protocol. The<br />
searches are only executed for IP packets.<br />
l<br />
l<br />
The search setIP.key1 identifies a set element where the first key matches an IP<br />
packet’s destination address (the field ip.dst).<br />
The search setIP.key2 identifies a set element where the second key matches an<br />
IP packet’s source address (the field ip.src).<br />
Rules invoke one <strong>of</strong> two action functions, passing additional values as required by<br />
the action definition, including the search used.<br />
l<br />
l<br />
When a matching element is found for either key, the action increments a counter<br />
in the element.<br />
When no matching element is found for either key, the action inserts an element<br />
into the set to match the current packet.<br />
//<br />
// A simple application to count the packets<br />
//<br />
// countncl.ncl<br />
//<br />
#include "ix_tcpip.ncl"<br />
Using Sets <strong>of</strong> Data to Classify Packets 163<br />
Revision 3.3, August 2001
Defining Sets and Searches<br />
set setIP<br />
{<br />
size_hint { 256 }<br />
}<br />
search setIP.key1(ip.dst)<br />
{<br />
requires{ ip }<br />
}<br />
search setIP.key2(ip.src)<br />
{<br />
requires{ ip }<br />
}<br />
predicate insertDst { ip && (! setIP.key1) }<br />
predicate insertSrc { ip && (! setIP.key2) }<br />
rule found1 { setIP.key1 }<br />
{ incrementSetElement(1, ip.dst, setIP.key1) }<br />
rule found2 { setIP.key2 }<br />
{ incrementSetElement(2, ip.src, setIP.key2) }<br />
rule new3 { insertDst }<br />
{ insertSetElement(3, ip.dst, setIP.key1) }<br />
rule new4 { insertSrc }<br />
{ insertSetElement(4, ip.src, setIP.key2) }<br />
For More Information<br />
For more information on defining sets and searches in NCL, see Chapter 6, “Network<br />
Classification Language (NCL),” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Defining Sets<br />
in ASL<br />
To use the sets and searches that you define in NCL, your <strong>ACE</strong> initialization code<br />
must include a header file containing set structure declarations that match the NCL<br />
definitions. The <strong>ACE</strong> initialization function must create each set structure using the<br />
ASL function ix_set_new.<br />
The set structure is created on initialization <strong>of</strong> the <strong>ACE</strong>. A mismatch between the<br />
NCL and ASL declarations results in a run-time error.<br />
Action code in the <strong>ACE</strong> can reuse an existing set structure for another set <strong>of</strong> the same<br />
size or smaller by using the function ix_set_init. Again, if the reinitialization does<br />
not match the set’s NCL declaration, a run-time error results.<br />
Example<br />
The following code fragment is part <strong>of</strong> the <strong>ACE</strong> initialization code. It extends the<br />
<strong>ACE</strong> structure to contain a set, and later creates the set as part <strong>of</strong> the <strong>ACE</strong>:<br />
//extend <strong>ACE</strong> structure to include set<br />
struct ace1<br />
{<br />
ix_ace base_ace;<br />
164 Using Sets <strong>of</strong> Data to Classify Packets<br />
Revision 3.3, August 2001
Initializing and Populating Sets<br />
ix_set *setp; // creates set when creating the <strong>ACE</strong><br />
}<br />
...<br />
// on creation, name setIP links it to the NCL<br />
ix_set_new (&acep->setp, 1, 256, "setIP", &acep->ace);<br />
Initializing and Populating Sets<br />
Creating the set structure does not generate any elements with which to populate it.<br />
You can populate a set with an initial set <strong>of</strong> elements, then later add or delete<br />
elements using actions, or you can populate it entirely through actions.<br />
In the action code for the <strong>ACE</strong>, define the action functions invoked by the NCL rules<br />
to retrieve data from a set or place data in a set, based on the results <strong>of</strong> searches.<br />
l<br />
l<br />
l<br />
To create an element, use the ASL function ix_element_new, then initialize the<br />
key values using the function ix_element_init_keys. To associate application<br />
data with the element, access the ix_element->user_info field directly.<br />
To insert the new element in a set, use the function ix_set_insert_element, or<br />
extract the insertion location from the search result, and pass it to the function<br />
ix_set_insert_at_location.<br />
To remove the element from the set, use the function ix_set_remove_element or<br />
ix_set_remove_at_location.<br />
— You can reuse an element that you have removed from a set by reinitializing<br />
the keys.<br />
— You can reuse a removed element in a different set by using the function<br />
ix_element_init, then reinitializing the keys.<br />
Example<br />
The action code for the <strong>ACE</strong> defines the four action functions invoked by the rules.<br />
Each action requires three arguments in addition to the two passed automatically.<br />
The rules pass these additional values to the action on invocation.<br />
// utility fn to construct print string from search result<br />
void my_search_result (ix_search *rsltp, char *buf)<br />
{<br />
switch (ix_set_get_search_result (rsltp)) {<br />
case NOT_RUN:<br />
sprintf(buf, "ix_search = %p, NOT_RUN", rsltp);<br />
break;<br />
case MISS:<br />
sprintf(buf, "ix_search = %p, MISS", rsltp);<br />
break;<br />
case HIT:<br />
sprintf(buf, "ix_search = %p, HIT", rsltp);<br />
break;<br />
default:<br />
my_error_handler((ix_error) 0, "my_search_result failed.");<br />
}<br />
}<br />
Revision 3.3, August 2001<br />
Using Sets <strong>of</strong> Data to Classify Packets 165
Initializing and Populating Sets<br />
//<br />
// ACTION FUNCTION DEFINITIONS<br />
//<br />
int incrementSetElement (ix_ace *ace, ix_buffer buf,<br />
int rule,<br />
int key,<br />
ix_search *rsltp)<br />
{<br />
ix_element *elemp;<br />
int *myData;<br />
char cbuf[128];<br />
my_search_result(rsltp, cbuf);<br />
printf("\t%d) incrementSetElement(%d, 0x%x, %s)\n",<br />
count, rule, key, cbuf);<br />
elemp = ix_set_get_element_from_search_obj(rsltp);<br />
myData = (int*) elemp->user_data;<br />
*myData += 1;<br />
}<br />
return 0;<br />
int insertSetElement(ix_ace *ace, ix_buffer buf,<br />
int rule,<br />
int key,<br />
ix_search *rsltp)<br />
{<br />
ix_element *elemp;<br />
ix_error err;<br />
int *myData;<br />
char cbuf[128];<br />
ace1 *myAce = (ace1*) ace;<br />
ix_set *setIPp = myAce->setIPp;<br />
my_search_result(rsltp, cbuf);<br />
printf("\t%d) insertSetElement(%d, 0x%x, %s)\n",<br />
count, rule, key, cbuf);<br />
err = ix_element_new(&elemp, 1);<br />
if (err) my_error_handler(err, "ix_element_new(&elemp, 1)");<br />
err = ix_element_init_keys(elemp, 1, key);<br />
if (err) my_error_handler(err,<br />
"ix_element_init_keys(elemp, 1, key)");<br />
myData = (int*) malloc(size<strong>of</strong>(int));<br />
*myData = 1;<br />
elemp->user_data = (void*) myData;<br />
166 Using Sets <strong>of</strong> Data to Classify Packets<br />
Revision 3.3, August 2001
How to Use Sets and Searches<br />
err = ix_set_insert_at_location(setIPp, rsltp, elemp);<br />
if (err) my_error_handler(err,<br />
"ix_set_insert_at_location(setIPp, rsltp, elemp)");<br />
}<br />
return 0;<br />
For More Information<br />
For more information on creating and using sets in ASL, see Chapter 4, “The ASL<br />
Core Support Package API,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
How to Use Sets and Searches<br />
The <strong>ACE</strong> runtime executes searches when it runs the classification code for an<br />
incoming packet. For each incoming packet, the <strong>ACE</strong> runtime tries every search<br />
defined in the NCL file. If the requires clause succeeds, the <strong>ACE</strong> runtime executes<br />
the search and stores the result in the corresponding ASL set object.<br />
You can also use the ASL set search functions to initiate a search anywhere in your<br />
action code. For example, you might want to initiate a search in response to an event<br />
or a message.<br />
Using<br />
Searches in<br />
Rules<br />
You can refer to a search by name on either side <strong>of</strong> a rule. How it is used depends on<br />
which side <strong>of</strong> the rule it is on.<br />
l<br />
l<br />
When used on the left side <strong>of</strong> a rule as part <strong>of</strong> the predicate, the search name acts<br />
as a Boolean expression. It succeeds when the search was executed and found a<br />
matching record in the set. If the search was not executed because the requirements<br />
were not met, or if it was executed but failed to find a matching element,<br />
the expression evaluates to FALSE.<br />
When you pass a search name as an action argument on the right side <strong>of</strong> a rule,<br />
the action can use the passed search object to obtain the result <strong>of</strong> the search (HIT,<br />
MISS, or NOT_RUN), and either the found element or a location at which to insert a<br />
new element in the set.<br />
Using Actions<br />
to Modify Sets<br />
When a rule passes a search name to an action, the action function receives a search<br />
object. This object contains:<br />
l<br />
l<br />
l<br />
The result <strong>of</strong> the search, one <strong>of</strong> the constants HIT, MISS, or NOT_RUN. Use the function<br />
ix_set_get_search_result to extract this value.<br />
If the search was successful (that is, the result is HIT), the search object contains<br />
the found element.<br />
If the search was unsuccessful (that is, the result is MISS), the search object<br />
contains a location at which to insert a new element in the set.<br />
Using Sets <strong>of</strong> Data to Classify Packets 167<br />
Revision 3.3, August 2001
How to Use Sets and Searches<br />
Use the function ix_set_get_element_from_search_obj to extract the element or<br />
insertion location. If the search was not run (that is, the result is NOT_RUN), this function<br />
returns NULL.<br />
You can take actions based on the fact <strong>of</strong> a search succeeding or failing, without<br />
regard for the data portion <strong>of</strong> the set element. For example, an action can simply set<br />
the target for the packet based on whether one <strong>of</strong> the searches succeeds.<br />
An action function can also modify a set element by changing its associated data. For<br />
example, when you have identified a packet that is coming from one <strong>of</strong> the interesting<br />
addresses, you can increment a counter in the matching element.<br />
You can look at or copy the data in a matching element, and take actions based on that<br />
data. For example, after a packet comes in from a particular address and you have<br />
incremented the counter in the matching element, you can check whether the counter<br />
has reached a certain value. If it has, you can build a message from it and send it to<br />
the host application in an upcall.<br />
An action function can create a new set element, using the search result’s insertion<br />
location. It can also delete a set element, directly or after a delay. To delay an action<br />
on an element, make the action function schedule an event, and delete the element in<br />
the event callback function.<br />
For more information on set, element, and event manipulation, see Chapter 4, “The<br />
ASL Core Support Package API,” in the <strong>IXA</strong> <strong>SDK</strong> Reference.<br />
Deleting Sets<br />
Use the function ix_set_delete to delete a set and all remaining elements.<br />
To simply remove the set elements without destroying them, use the function<br />
ix_set_foreach to walk through the set.<br />
168 Using Sets <strong>of</strong> Data to Classify Packets<br />
Revision 3.3, August 2001
Index<br />
A<br />
<strong>ACE</strong> 5<br />
accelerated 7<br />
action code part 105<br />
binding 38<br />
blocking not allowed in 120, 124<br />
C structure 5, 106<br />
classification part 99<br />
compared to task 124<br />
conventional vs. accelerated 7<br />
creating 10, 22<br />
creating C structures in 106<br />
defining behavior <strong>of</strong> 108<br />
defining packet flow for 48<br />
initializing 106<br />
languages for writing 6<br />
launching 10<br />
programmatically 46<br />
with script 38<br />
library 87<br />
L2 bridging 91<br />
L3 forwarder 89<br />
NAT 94<br />
packet processing in 5, 99<br />
packet reception 83<br />
packet transmission 85<br />
predefined 7, 87<br />
rules 101<br />
stack 88<br />
targets in 48<br />
using to receive and transmit packets 48<br />
utility functions in 109<br />
what type to use for what task 8<br />
action code 105<br />
action functions 108<br />
callbacks 108<br />
compiling 30<br />
utility functions 108<br />
see also actions, action functions<br />
action functions 5, 108<br />
interaction with rules 108<br />
predefined 109<br />
return values 108<br />
syntax 108<br />
using to create and delete set elements 167<br />
what they do 110<br />
see also actions, action code<br />
Action Services Library, see ASL<br />
actions 5<br />
executing 103<br />
using to direct packets 51<br />
using to modify sets 167<br />
using to populate and modify sets 165<br />
see also action code, action functions<br />
active computing element, see <strong>ACE</strong><br />
API overview 17<br />
applications 1<br />
building blocks 18<br />
input and output 79<br />
L2 bridging 91<br />
L3 forwarding 89<br />
NAT 94<br />
TCP/IP stack 88<br />
communicating within 113, 139<br />
compiling 29<br />
configuring and starting 35<br />
deploying 17<br />
initializing <strong>ACE</strong>s 10<br />
linking 29<br />
organization <strong>of</strong> 3<br />
types 1<br />
argument passing for crosscalls 133<br />
client side 134<br />
deferred calls 137<br />
one-way calls 136<br />
server side 135<br />
two-way calls 136<br />
ASL 17<br />
contents 106<br />
creating objects 106<br />
error codes 24<br />
predefined action functions in 109<br />
return values 24<br />
using for sets and searches 165<br />
using to write <strong>ACE</strong> initialization and action code<br />
105<br />
writing action code in 105<br />
asynchronous crosscalls 120, 121, 123<br />
handling response with callback 121<br />
specifying timeouts for 122<br />
Index 169<br />
Revision 3.3, August 2001
B<br />
bindings 48<br />
full names <strong>of</strong> targets 21<br />
interface <strong>ACE</strong>s 82<br />
L3 forwarder <strong>ACE</strong> targets 90<br />
setting in configuration file 38<br />
setting programmatically 49<br />
stack <strong>ACE</strong> targets 88<br />
static 60<br />
targets 48<br />
unbound targets 50<br />
blocking for crosscalls 120, 124<br />
building blocks 18<br />
for input and output 79<br />
for L2 bridging 91<br />
for L3 forwarding 89<br />
for network address translation 94<br />
for TCP/IP stack handling 88<br />
C<br />
.c files 30<br />
C structures in ASL 23<br />
callbacks 108<br />
defining 109<br />
for deferred crosscall operations 109, 117<br />
for scheduled events 109<br />
CAP 10<br />
using for crosscalls 115<br />
using for OMS session 21<br />
classification 99<br />
definition 2<br />
role <strong>of</strong> protocol definition 102<br />
rule evaluation 103<br />
rules 101<br />
using rules and protocol definitions 100<br />
using sets rather than rules 162<br />
clients, crosscall 114<br />
communication access process, see CAP<br />
communication between <strong>ACE</strong>s and objects 113, 139<br />
see also crosscalls<br />
compilers 20<br />
compiling 32, 33<br />
action and initialization code 30<br />
micro<strong>ACE</strong>s 32<br />
NCL 30<br />
using makefiles 33<br />
configuration files 35<br />
samples for library <strong>ACE</strong>s 39<br />
configuration scripts 35<br />
contacting <strong>Intel</strong> xii<br />
control plane 4<br />
conventional <strong>ACE</strong>, defined 7<br />
conventions, typographical xi<br />
core components 7, 55<br />
in micro<strong>ACE</strong> architecture 57<br />
writing 61<br />
core processor 14<br />
memory shared with microengines 65<br />
creating <strong>ACE</strong>s 22<br />
crosscall interfaces 12<br />
C structure 23<br />
defining 114, 116<br />
example definition 140<br />
initializing and terminating 125<br />
using to organize operations 117<br />
crosscall references 114<br />
crosscalls 12, 113<br />
and threads 124<br />
argument directions 122<br />
deferred operations 120, 121<br />
callback functions for 117, 121, 123<br />
defining callback functions 109<br />
defining operations 118<br />
example 139<br />
writing the client 144<br />
writing the server 152<br />
full names <strong>of</strong> 21<br />
implementing callback functions 117, 130<br />
implementing operations 116, 130<br />
initializing the client 125<br />
example 125<br />
initializing the server 128<br />
example 129<br />
integrating into applications 123<br />
invoking remotely 130<br />
example 131<br />
making and receiving 114<br />
making two-way calls from <strong>ACE</strong>s not allowed 120<br />
naming operations 119<br />
one-way operations 120<br />
opening a connection from the client 131<br />
organizing operations into interfaces 117<br />
passing arguments 133<br />
for deferred call 137<br />
for one-way call 136<br />
for two-way call 136<br />
on client side 134<br />
on server side 135<br />
skeletons, example 143<br />
stubs, example 140<br />
synchronous and asynchronous operations 120<br />
two-way operations 120<br />
using stub functions 130<br />
using to configure input <strong>ACE</strong> 80<br />
handling return values 84<br />
using to configure library <strong>ACE</strong>s 124<br />
using to configure micro<strong>ACE</strong>s 68<br />
when to use 115<br />
customer support xii<br />
170 Index<br />
Revision 3.3, August 2001
D<br />
data processing plane 3<br />
data sets 161<br />
data structures 161<br />
for core processor 161<br />
shared with microengines 65<br />
default targets 49<br />
deferred crosscall operations 120, 121, 123<br />
callback functions for 117, 121<br />
where callbacks are defined 109<br />
delaying actions 106<br />
deploying applications 17<br />
development environment 14<br />
development tools 18, 20, 29<br />
dispatch loop<br />
controlling packet flow 73<br />
dispatch loops 71<br />
application-defined global registers 73<br />
example 73<br />
global registers 72<br />
in micro<strong>ACE</strong> architecture 58<br />
returning values to 75<br />
writing 71<br />
disposing <strong>of</strong> packets 103<br />
dl_buffer_handle register 72<br />
dropping packets 50<br />
.dwp files 56<br />
dynamic NAT 94<br />
E<br />
elements 161<br />
adding to sets 167<br />
C structure 23<br />
deleting from sets 168<br />
searching for in sets 161<br />
embedded Linux 14<br />
embedded operating system 18<br />
environment variable IXROOT xii<br />
error codes 24<br />
event processing 106<br />
events 23<br />
C structure 23<br />
using to delay set element removal 168<br />
example applications 88<br />
exception handling in micro<strong>ACE</strong>s 62<br />
flagging in microblocks 76<br />
writing a handler 64<br />
F<br />
file types 30<br />
firewall applications 1<br />
fragments and NAT 95<br />
FTP and NAT 95<br />
G<br />
gcc compiler 30<br />
GNU toolchain 30<br />
H<br />
handler functions 108<br />
for asynchronous operations 109<br />
for micro<strong>ACE</strong> exception packets 64<br />
hardware architecture 14<br />
hardware configurations 14<br />
I<br />
ICMP errors and NAT 95<br />
.idl files 30<br />
IDL, see <strong>IXA</strong> IDL<br />
in arguments for crosscalls 122<br />
initialization 10<br />
<strong>of</strong> <strong>ACE</strong>s 22<br />
<strong>of</strong> crosscall interfaces 125<br />
<strong>of</strong> function pointers for crosscalls 130<br />
<strong>of</strong> micro<strong>ACE</strong> Resource Manager 58<br />
<strong>of</strong> OMS 21<br />
initialization functions 22<br />
for <strong>ACE</strong>s 22, 106<br />
for micro<strong>ACE</strong>s 62<br />
inout arguments for crosscalls 122<br />
input <strong>ACE</strong>s 79, 83<br />
configuring with crosscalls 80, 83<br />
handling crosscall return values 84<br />
initializing 81<br />
logicalMgmt interface 80<br />
portMgmt interface 80<br />
installation directory pathname xii<br />
<strong>Intel</strong>, contacting xii<br />
interface <strong>ACE</strong>s 79<br />
binding 82<br />
configuring with crosscalls 80<br />
initializing 81<br />
input <strong>ACE</strong> 83<br />
integrating with your application 80<br />
naming 82<br />
output <strong>ACE</strong> 85<br />
source code location 81<br />
starting 82<br />
interface definition language, see <strong>IXA</strong> IDL<br />
interfaces, see network interfaces, ports, or crosscalls,<br />
crosscall interfaces<br />
interobject communication 113, 139<br />
intrusion detection applications 1<br />
IP addresses, setting for ports 38<br />
IP masquerade (port translation) NAT 95<br />
ix_action_default function 109<br />
IX_EXCEPTION 62<br />
<strong>IXA</strong> IDL 18<br />
Index 171<br />
Revision 3.3, August 2001
syntax 118<br />
using to define crosscall interfaces 114, 116<br />
<strong>IXA</strong> IDL compiler 18, 29<br />
generated files 116<br />
IXP 1200 processor 14<br />
IXP1200 Microengine Development Environment 18<br />
IXROOT environment variable xii<br />
ixstart script 35<br />
ixsys.config file 35<br />
K<br />
key point, explanation <strong>of</strong> xi<br />
keys, set 162<br />
associating with protocol fields 162<br />
definition 161<br />
L<br />
L2 bridging library <strong>ACE</strong> 91<br />
configuring 94<br />
packet processing in 92<br />
sample configuration files 40<br />
starting 93<br />
L3 forwarder library <strong>ACE</strong> 89<br />
binding targets 90<br />
configuring 90<br />
sample configuration files 42<br />
starting 90<br />
languages for <strong>ACE</strong> development 18, 20<br />
layer three forwarding 89<br />
layer two bridging 91<br />
ld linker 30<br />
libraries, run-time 18<br />
library <strong>ACE</strong>s 87<br />
defined 7<br />
L2 bridging 91<br />
L3 forwarder 89<br />
NAT 94<br />
sample configurations files 39<br />
used in example applications 88<br />
using crosscalls to configure 124<br />
Linux 14<br />
development tools 18<br />
embedded on IXP1200 18<br />
TCP/IP stack 18, 88<br />
load balancing (virtual server) NAT 95<br />
load balancing applications 2<br />
logicalIfMgmt interface for input <strong>ACE</strong> 80<br />
M<br />
makefiles 33<br />
management plane 4<br />
management programs 22<br />
in micro<strong>ACE</strong> architecture 57<br />
memory shared between microengines and core<br />
processor 65<br />
micro<strong>ACE</strong> Resource Manager 13<br />
micro<strong>ACE</strong>s 7, 32<br />
components and terms 56<br />
configuring with crosscalls 68<br />
defining packet flow with dispatch loop 71<br />
design example 77<br />
exception handling 62, 76<br />
initializing 62<br />
launching 38<br />
library <strong>ACE</strong>s 87<br />
loading 58<br />
macros 18<br />
microcode image files 38<br />
processing pipeline 59<br />
programming model 55<br />
project files 56<br />
Resource Manager 17<br />
terminating 64<br />
transmitting packets from 75<br />
writing the core component 61<br />
microblock groups 68<br />
in micro<strong>ACE</strong> architecture 57<br />
microblocks 7, 55, 75<br />
combining into groups 68<br />
defining packet flow iwth dispatch loop 71<br />
determining packet disposition 75<br />
flagging exceptions 76<br />
in micro<strong>ACE</strong> architecture 57<br />
sink 70<br />
source 69<br />
transform 70<br />
types 69<br />
using to transmit packets 75<br />
microcode 7<br />
compiling 58<br />
development tools 18<br />
macros for micro<strong>ACE</strong>s 18<br />
using Workbench to edit 56<br />
microcode images 58<br />
specifiying files for loading 38<br />
Microengine Development Environment 18<br />
microengine toolchain 32<br />
microengines 14<br />
memory shared with core processor 65<br />
threads 37<br />
N<br />
Name Server 21<br />
synchronous and asynchronous sessions 124<br />
named searches 162<br />
naming and referencing OMS objects 21<br />
172 Index<br />
Revision 3.3, August 2001
NAT library <strong>ACE</strong>s 94<br />
binding targets 97<br />
configuring 98<br />
handling <strong>of</strong> FTP, fragments, and ICMP 95<br />
packet processing in 94<br />
sample configuration files 44<br />
starting 96<br />
NCL 18, 99<br />
compiling 30<br />
using to declare sets 162–164<br />
using to define sets and searches 100<br />
NCL compiler 18, 29<br />
.ncl files 30<br />
nclcomp compiler 29<br />
network address translation (NAT) 94<br />
Network Classification Language, see NCL 169<br />
network interfaces 2<br />
configuring 38<br />
receiving and transmitting on with interface <strong>ACE</strong>s<br />
79<br />
see also ports<br />
note, explanation <strong>of</strong> xi<br />
O<br />
.o files 30<br />
Object Management System, see OMS<br />
objects 23<br />
creating in <strong>ACE</strong> 106<br />
in an <strong>IXA</strong> application 23<br />
naming 21<br />
OMS 10<br />
Name Server 21<br />
Resolver 20<br />
services 17<br />
synchronous and asynchronous entry points 124<br />
one-way crosscall operations 120<br />
out arguments for crosscalls 122<br />
output <strong>ACE</strong>s 79, 85<br />
initializing 81<br />
output ports for packets 75<br />
P<br />
packet flow 48<br />
defining with dispatch loops 71<br />
defining with targets 48<br />
monitoring with sets 162<br />
through micro<strong>ACE</strong>s 73<br />
packets 2<br />
associating with data using sets 162<br />
classification by <strong>ACE</strong>s 99<br />
classification overview 2<br />
defining traffic flow 11<br />
through micro<strong>ACE</strong>s 59<br />
with targets 47<br />
directing to a target 51<br />
disposing <strong>of</strong> 103<br />
dropping 50<br />
forcing serial processing <strong>of</strong> 51<br />
handling with TCP/IP stack 88<br />
receiving 83<br />
receiving and transmitting with interface <strong>ACE</strong>s 79<br />
role <strong>of</strong> protocol definitions in classifying 102<br />
sets <strong>of</strong> 100<br />
setting output port 75<br />
targets as destinations for 48<br />
transferring with crosscalls vs. targets 115<br />
transmitting 85<br />
transmitting from microblocks 75<br />
using an <strong>ACE</strong> to receive and transmit 48<br />
using set searches to check addresses <strong>of</strong> 104<br />
populating sets 165<br />
port translation (IP masquerade) NAT 95<br />
portMgmt interface for input <strong>ACE</strong> 80<br />
ports 2<br />
configuring 35, 38<br />
enabling and disabling 84<br />
IP addresses 85<br />
MAC address 84<br />
managing logical configuration 85<br />
managing physical configuration 84<br />
receiving and transmitting on with interface <strong>ACE</strong>s<br />
79<br />
statistics 84<br />
predicates 100<br />
contents 101<br />
evaluating 103<br />
processing pipeline in micro<strong>ACE</strong>s 59<br />
programming interface overview 17<br />
project file, Workbench 56<br />
protocol definitions 102<br />
definition 100<br />
role in packet classification 102<br />
TCP/IP 102<br />
using to classify packets 100<br />
protocol fields 100<br />
associating with keys 162<br />
Q<br />
quality <strong>of</strong> service (QoS) applications 2<br />
R<br />
receiving packets 83<br />
reference, explanation <strong>of</strong> xi<br />
remote calls 114<br />
remote procedure invocation 113<br />
synchronous and asynchronous 120<br />
Index 173<br />
Revision 3.3, August 2001
Resolver 20<br />
communicating with 22<br />
synchronous and asynchronous sessions 124<br />
Resource Manager 13, 17<br />
API for memory management 66<br />
in micro<strong>ACE</strong> architecture 57<br />
initializing 58<br />
return values 24<br />
for action functions 108<br />
for API functions 24<br />
for crosscalls 122<br />
RMON statistical monitoring applications 1<br />
rules 5, 99<br />
action functions in 101<br />
components <strong>of</strong> 101<br />
definition 100, 101<br />
evaluating 103<br />
predicates 101<br />
using instead <strong>of</strong> sets 162<br />
using set searches in 167<br />
using to trigger actions 100<br />
what they do 104<br />
running applications 35<br />
run-time libraries 18<br />
S<br />
.s files 30<br />
sample applications 88<br />
scheduled event callbacks 109<br />
scripts, startup and configuration 35<br />
<strong>SDK</strong> components 17<br />
system s<strong>of</strong>tware 18<br />
<strong>SDK</strong>installpath meaning xii<br />
searches in sets 162<br />
and rules 100<br />
ASL code requirements 165<br />
defining 162<br />
how to use 167–168<br />
overview 161<br />
results 163<br />
using in rules 167<br />
using to check incoming packet addresses 104<br />
serial processing <strong>of</strong> packets 51<br />
servers, crosscall 114<br />
set elements, see elements 169<br />
set keys 162<br />
associating with protocol fields 162<br />
sets 161<br />
and rules 100<br />
ASL code requirements 165<br />
C structure 23<br />
creating and deleting elements using action<br />
functions 167<br />
declaring using NCL 162–164<br />
defining 162<br />
delaying actions on elements 168<br />
deleting 168<br />
how to use 167–168<br />
overview 161<br />
populating 165<br />
using actions to modify 165, 167<br />
using to associate data with packets 162<br />
using to classify packets 162<br />
using to collect data about packet flow 162<br />
using to keep tables <strong>of</strong> addresses 104<br />
when to use 162<br />
shared memory, microengines and core processor 65<br />
sink microblocks 70<br />
skeletons, generated for crosscalls 116<br />
s<strong>of</strong>tware development tools 18, 29<br />
source microblocks 69<br />
stack <strong>ACE</strong> 87, 88<br />
defined 9<br />
starting and configuring 88<br />
stack, TCP/IP for Linux 18<br />
starting applications 35<br />
startup scripts 35<br />
static bindings 60<br />
static NAT 94<br />
statistical monitoring (RMON) applications 1<br />
structures for <strong>ACE</strong> programming framework 23<br />
creating in <strong>ACE</strong> 106<br />
stub files, example 140<br />
stub functions 114<br />
generated source files 117<br />
using to invoke crosscalls 130<br />
support for <strong>Intel</strong> xii<br />
symbols xi<br />
synchronous and asynchronous crosscalls 120<br />
synchronous crosscalls 120<br />
system <strong>ACE</strong>s 7<br />
interface 79<br />
stack <strong>ACE</strong> 88<br />
system configuration file 37<br />
system s<strong>of</strong>tware 18<br />
OMS 10<br />
Resource Manager 13<br />
starting 35<br />
T<br />
tao_idl compiler 29<br />
targets 11, 50<br />
and packet flow 47<br />
binding 48<br />
binding in configuration file 38<br />
C structure 23<br />
creating 50<br />
default 49<br />
defining 50<br />
directing packets to 51<br />
174 Index<br />
Revision 3.3, August 2001
full names <strong>of</strong> 21<br />
L3 forwarder <strong>ACE</strong> 90<br />
overview 11<br />
stack <strong>ACE</strong> 88<br />
unbound 50<br />
vs. crosscalls, transferring packets with 115<br />
tasks 10<br />
compared to <strong>ACE</strong> 124<br />
defined in OMS 10<br />
using with crosscalls 115, 124<br />
TCP fragments and NAT 95<br />
TCP/IP protocol definition for NCL 102<br />
TCP/IP stack, Linux 18, 88<br />
termination functions 22<br />
for <strong>ACE</strong>s 22<br />
for crosscall interfaces 125<br />
for micro<strong>ACE</strong>s 64<br />
threads 37<br />
and crosscalls 124<br />
on microengines 8, 37<br />
timeouts for asynchronous crosscalls 122<br />
times and events 23<br />
toolchains 20<br />
tools for developers 18, 29<br />
traffic flow 11<br />
through <strong>ACE</strong>s 11<br />
through micro<strong>ACE</strong>s 59, 73<br />
through targets 47<br />
transform microblocks 70<br />
transmitting packets 85<br />
two-way crosscall operations 120<br />
typographical conventions xi<br />
U<br />
unbound targets 50<br />
.u<strong>of</strong> files 58<br />
user <strong>ACE</strong>s 7<br />
utility functions in <strong>ACE</strong>s 109<br />
V<br />
variable IXROOT xii<br />
virtual method table (VMT) 130<br />
for callback implementations 117, 130<br />
for crosscall implementations 116, 130<br />
virtual private networks (VPN) 1<br />
virtual server (load balancing) NAT 95<br />
voice over IP (VOIP) applications 2<br />
WXYZ<br />
warning, explanation <strong>of</strong> xi<br />
Workbench 56<br />
project files 56<br />
Index 175<br />
Revision 3.3, August 2001
176 Index<br />
Revision 3.3, August 2001
Revision 3.3, August 2001<br />
177
<strong>Intel</strong> Corporation<br />
2200 Mission College Blvd.<br />
PO Box 58119<br />
Santa Clara, CA 95052-8119 USA<br />
Tel: 800.628.8686<br />
www.intel.com<br />
Revision 3.3, August 2001