zcmux guide 5010loi apr 15 2010

23
Zero Copy Ethernet MUX User Guide

Upload: maihoonna

Post on 15-Oct-2014

97 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: ZCmux Guide 5010LOI Apr 15 2010

Zero Copy Ethernet MUX User Guide

Page 2: ZCmux Guide 5010LOI Apr 15 2010

Table of ContentsGuide Change List......................................................................................................................................3Introduction................................................................................................................................................4ZC­MUX Requirements.............................................................................................................................4Adding The Ethernet ZC­MUX to the BSP...............................................................................................4ZC­MUX Configuration............................................................................................................................5

Creating MUXes....................................................................................................................................5Virtual Port Configuration....................................................................................................................6Sample MUX Configuration.................................................................................................................61:1 MUX configuration.........................................................................................................................8

Ethernet MUX Filters.................................................................................................................................9Transmit Filters......................................................................................................................................9Receive Filters.....................................................................................................................................10Complete MUX Configuration Example.............................................................................................11

Advanced Features of the ZC­MUX.........................................................................................................11Global MUX Configuration.................................................................................................................11

ghnetv1 TCPIP stack and the ZC­MUX...................................................................................................12ghnetv2 TCPIP stack and the ZC­MUX...................................................................................................12Link time memory for MUX (optional)...................................................................................................13ZC­MUX­vport API.................................................................................................................................14

Data types............................................................................................................................................14Methods...............................................................................................................................................14

Stack Porting Guide..................................................................................................................................17High Level Differences between ZC­MUX and O­MUX....................................................................17Vport Initialization..............................................................................................................................17Transmitting and Receiving Frames....................................................................................................19

Buffer and Frame Indexes...............................................................................................................19Transmitting Frames.......................................................................................................................20Receiving Frames (Preparation)......................................................................................................21Event Handling...............................................................................................................................21

Copyright (c) 2010 by Green Hills Software, Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission from Green Hills Software, Inc.

02­05­2010. MUX doc version 1.10 2Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 3: ZCmux Guide 5010LOI Apr 15 2010

Guide Change List(This page is intentionally left blank)

02­05­2010. MUX doc version 1.10 3Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 4: ZCmux Guide 5010LOI Apr 15 2010

IntroductionThe Zero Copy Ethernet MUX (ZC­MUX) is a software­simulated OSI layer 2 Ethernet switch.  It attaches to a physical Ethernet device and provides multiple virtual Ethernet devices/ports (vports). Each vport has it's own MAC address, and is for most purposes indistinguishable from a hardware Ethernet device.  The ZC­MUX performs the same job as the Original Ethernet MUX (O­MUX), however uses a different API to transmit and receive Ethernet frames to achieve better performance. Any stack1 using the Ethernet IODevice API can be ported to use the  ZC­MUX­vport API.

ZC­MUX Requirements The GHS Ethernet device driver must support “promiscuous mode”.

Adding The Ethernet ZC­MUX to the BSPThe ZC­MUX requires the BSP reserve a portion of physical memory for MUX use.  The amount of memory required depends on the number of vports.  The minimum amount of memory required is:

(NUM_TX_BUFS * <number of vports>) + NUM_UPLINK_RX_BUFS

It is recommended that at least 32 Pages are allocated per vport and 32 Pages allocated for the physical port.  There are many ways of reserving physical memory (see Reserving Memory Regions in the INTEGRITY BSP User's Guide.)  The following is an example of how to reserve space under the  name __ghs_MUX1_buffers in the initial memory map using MemoryReservations:

MemoryReservation __ghsentry_reservedmem_bspMUXbuffers = /* 512K for MUX buffers, page-aligned start, end */ { MEMORY_RWE, 0, 0, 1 * 512 * 1024 - 1, RAM_MemoryType, false, 0xfffff000, 0xfffff000, "__ghs_MUX1_buffers" };

Note: Each MUX requires its own reservation of memory (as opposed to the O­MUX which uses buffers from __ghsentry_reservedmem_bsptcpipbuffers.)

The MUX uses the configurationIODevice.  Ensure the configuraitonIODevice is in your BSP else add the configurationIODevice by adding configuration_iodevice.c to libbsp.gpj .

The ZC­MUX server can run in either Kernel Space or Virtual Address Space.  To add a ZC­MUX server to Kernel Space, compile the libmux library by adding the following to the kernel project file:

-lmux

To run the ZC­MUX in a virtual AddressSpace link the virtual AddressSpace with the libvmux library, declare a variable __ghs_tcpip_is_virtual of type char and set it to 1, and invoke SM_MUXEntry().   I.e. create a Program with the following in the project file:

1 For simplicity, “stack” refers to any software that interfaces directly with an Ethernet port (physical or virtual).02­05­2010. MUX doc version 1.10 4

Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.Green Hills Proprietary Information

Page 5: ZCmux Guide 5010LOI Apr 15 2010

-lvmux

The following should be sufficient to start a Virtual ZC­MUX in that AddressSpace:

char __ghs_tcpip_is_virtual = 1;

int main(){ SM_MUXEntry();}

ZC­MUX ConfigurationSpecial symbols linked into the ZC­MUX AddresSpace control the creation and configuration of Ethernet MUXes.  The following section describes how to declare such symbols and configure the MUXes.

Creating MUXesMUX configuration is done with global variables linked into the Address Space where the ZC­MUX is located (Kernel Space for a kernel resident MUX or the Virtual Address Space of the virtual ZC­MUX application.)  To add an Ethernet MUX to the system, create a global variable named _ghsentry_smmux_XXX where “XXX” is an arbitrary name that is unique to the MUX being created. The variable must be of type struct muxconfig, and must contain the configuration information for the MUX.  The structure can be found in mux/mux_config.h and is defined as follows:

struct muxconfig{ int id; // Mux's ID char *uplink_name; // stack name in BSPEthernetIODeviceNames EtherDevEntry *dentry; // ghs_ethernet driver int nports; // Number of Virtual ports char *buffer_name; // name of physical memory allocated for this MUX};

The id field should contain a unique id that stacks can use to identify a MUX.  It is also used to identify a MUX when adding filters to it.

The uplink_name field contains the uplink's physical port name.  This is the EtherDev name assigned in BSPEthernetIODeviceNames1 as is relevant for legacy Ethernet IODevices.  This field can be NULL if only a virtual MUX between virtual ports and no uplink desired.

The dentry field is a pointer to the ghs_ethernet driver for the physical port.  If the physical port is a legacy Ethernet IODevice then dentry should be &mux_ethernet_driver_iod.

The nports field contains the number of virtual ports on this MUX.  This number must be at least 1, 

1 See Renaming an Ethernet IODevice in the INTEGRITY BSP User's Guide for information on setting up BSPEthernetIODeviceNames.

02­05­2010. MUX doc version 1.10 5Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 6: ZCmux Guide 5010LOI Apr 15 2010

and can be arbitrarily large, assuming the total number of vports on the system does not exceed MAX_ENET_MUX_VDEVS.

The buffer_name is the name of the buffer reserved by the BSP.  In the MemoryReservation example from above, buffer_name would contain __ghs_MUX1_buffers.

Virtual Port ConfigurationThe NetDevs1 array must be properly setup to assign MAC addresses and IP addresses to vports.  Vport configurations should begin after all physical port configurations in the NetDevs array and should be ordered according to the MUX's id and then vport number.  By default, the ZC­MUX assumes that there are two physical ports and will skip the first two physical ports when assigning NetDev entries. This can be optionally overridden by declaring the num_bsp_physical_interfaces variable in the AddressSpace of the ZC­MUX. 

/* This BSP has 4 physical interfaces. * Tell the MUX to skip 4 NetDev entries instead of the default 2 */const int num_bsp_physical_interfaces = 4;

Sample MUX ConfigurationThe following is a sample MUX configuration including sample BSPEthernetIODeviceNames and NetDevs definitions.  There are two physical ethernet devices, both assigned to a MUX.  Each MUX has 2 virtual ports.

/******** MUXes configuration *********/struct muxconfig __ghsentry_smmux_mux0 = { 0, "MUXEtherDev0", &mux_ethernet_driver_iod, 2, "__ghs_MUX0_buffers" };

struct muxconfig __ghsentry_smmux_mux1 = { 1, "MUXEtherDev1", &mux_ethernet_driver_iod, 2, "__ghs_MUX1_buffers" };/******** MUXes configuration END *********/

/******** BSPEthernetIODeviceNames configuration *********/char *BSPEthernetIODeviceNames[] = {

"MUXEtherDev0", // PHYSICAL Device 0"MUXEtherDev1", // PHYSICAL Device 1

// VIRTUAL port� MUX_0_VPORT_0� , � MUX_0_VPORT_1� ,

1For more information on setting up the NetDevs array refer to the INTEGRITY Networking Guide02­05­2010. MUX doc version 1.10 6

Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.Green Hills Proprietary Information

Page 7: ZCmux Guide 5010LOI Apr 15 2010

� MUX_1_VPORT_0� ,� MUX_1_VPORT_1� ,

};/******** BSPEthernetIODeviceNames configuration END *********/

/******** NetDevs configuration (usually found in global_tables.c) *********/#define IPAddress(a,b,c,d) ((a)<<24 | (b)<<16 | (c)<<8 | (d))struct NetInfo NetDevs[6] = {/* PHYSICAL Devices start first in NetDevs */

{ // PHYSICAL Device 0 (MUXEtherDev0)0x00,0xe0,0x0c,0x0,0x00,0x01, /* EthernetAddress */IPAddress(192, 168, 102, 1), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname1.ghs.com" /* hostname */

},{ // PHYSICAL Device 2 (MUXEtherDev1)

0x00,0xe0,0x0c,0x0,0x00,0x2, /* EthernetAddress */IPAddress(10, 0, 0, 1), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname2.ghs.com" /* hostname */

},

/* VIRTUAL ports follow after... */{ // MUX0's first MUX Vport (MUX_0_VPORT_0)

0x00,0xe0,0xbb,0xbb,0xbb,0x01,/* EthernetAddress */IPAddress(192, 168, 102, 2), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname3.ghs.com" /* hostname */

},{ // MUX0's second Vport (MUX_0_VPORT_1)

0x00,0xe0,0xbb,0xbb,0xbb,0x02,/* EthernetAddress */IPAddress(192, 168, 102, 3), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname4.ghs.com" /* hostname */

},{ // MUX1's first Vport (MUX_1_VPORT_0)

0x00,0xe0,0xbb,0xbb,0xbb,0x03,/* EthernetAddress */IPAddress(10, 0, 0, 2), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname5.ghs.com" /* hostname */

02­05­2010. MUX doc version 1.10 7Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 8: ZCmux Guide 5010LOI Apr 15 2010

},{ // MUX1's second MUX Vport (MUX_1_VPORT_1)

0x00,0xe0,0xbb,0xbb,0xbb,0x04, /* EthernetAddress */IPAddress(10, 0, 0, 3), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname6.ghs.com" /* hostname */

},}/******** NetDevs configuration END *********/

1:1 MUX configurationA 1:1 MUX, is a MUX configured with only one virtual port.  A 1:1 MUX can be used if the user wishes to use the ZC­MUX API instead of the underlying API such as the EnetIODevice API.  When configuring a 1:1 MUX, the NetDevs entry for the physical uplink and the virtual port SHOULD be the same.  While is NOT a requirement, certain optimizations can be performed if the entries share the same settings.  The following is a sample configuration for a 1:1 MUX:

/******** MUXes configuration *********/struct muxconfig __ghsentry_smmux_mux1 = { 0, "MUXEtherDev0", &mux_ethernet_driver_iod, 1, "__ghs_MUX1_buffers" };

/******** MUXes configuration END *********/

/******** BSPEthernetIODeviceNames configuration *********/char *BSPEthernetIODeviceNames[] = {

"MUXEtherDev0", // PHYSICAL Device 0� MUX_0_VPORT_0� , // VIRTUAL port

}/******** BSPEthernetIODeviceNames configuration END *********/

/******** NetDevs configuration *********/struct NetInfo NetDevs[2] = {/* PHYSICAL Devices (Uplink) */

{ // PHYSICAL Device 0 (MUXEtherDev0)0x00,0xe0,0x0c,0x0,0x00,0x01, /* EthernetAddress */IPAddress(192, 168, 102, 1), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname1.ghs.com" /* hostname */

},{ // Virtual Port (copy of above)

02­05­2010. MUX doc version 1.10 8Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 9: ZCmux Guide 5010LOI Apr 15 2010

0x00,0xe0,0x0c,0x0,0x00,0x01, /* EthernetAddress */IPAddress(192, 168, 102, 1), /* IPAddress */0, /* Gateway */0, /* NetMask */0, /* should be zero */0, /* NameServer */"hostname1.ghs.com" /* hostname */

},}

/* This BSP has 1 physical interfaces. * Tell the MUX to skip 1 NetDev entries instead of the default 2 */const int num_bsp_physical_interfaces = 1;

/******** NetDevs configuration END *********/

Ethernet MUX FiltersEthernet MUX filters allow the system designer to monitor, filter and modify all Ethernet traffic passing through the MUX.  This is particularly useful for imposing extra security on an untrusted stack. A filter is a function that is called by the MUX every time a particular virtual port attempts to transmit or receive an Ethernet frame.  The filter may passively monitor the frame, or it may modify the frame header or data.  If the filter does not return Success, then the MUX discards the frame without delivering it.  To create a filter, define a global variable of type struct muxfilter as described below. These variables must be linked into the MUX's address space.

struct muxfilter{ int mux_id; // Which Mux int port; // Which Virtual Port Error (*filter)(char *, int *); // filter Boolean modifies; // Does this filter modify data?};

The mux_id identifies the MUX containing the virtual port to which the filter attaches.

The port identifies the virtual port number, which is an integer from 0 to (nports­1).

The filter is a pointer to the filter function itself.  The arguments passed to the filter are a pointer to the Ethernet frame data and a pointer to the length of the frame, in bytes.  The filter may modify the frame data and length through these pointers.

The modifies field should be set to true (non­zero) if the filter potentially modifies the Ethernet frame data.

Transmit FiltersTransmit filters affect Ethernet frames transmitted from an application or stack attached to a particular vport.  The filter is called after the frame leaves the stack or application, but before it enters the MUX 

02­05­2010. MUX doc version 1.10 9Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 10: ZCmux Guide 5010LOI Apr 15 2010

switching logic (so transmit filters can affect the destination of the frame.)  If the filter does not return Success, the outgoing frame is silently discarded, and is never sent to other vports or the network.

To add a transmit filter to a virtual port on a MUX, add a global variable linked into the MUX's address space named __ghsentry_smmuxtxfilter_XXX where “XXX” is an arbitrary name that is unique to the filter being created.  The symbol must be of type struct muxfilter, and must contain configuration information for the filter.

For example, the following code creates a filter on vport 1 of the MUX with id 1 that rewrites the destination MAC address on all outgoing frames from the port.  This restricts the stack attached to that virtual port from being able to communicate with network peers using that any other destination MAC address.

static Error myfilter(char *buf, int *len){

static char destaddr[] = { 0x00,0x01,0x03,0xD6,0x18,0xD7 };memcpy(buf, destaddr, 6);return Success;

}

struct muxfilter __ghsentry_smmuxtxfilter_a = { 1, 1, myfilter, true };

Receive FiltersReceive filters affect Ethernet frames sent to an application or stack attached to a particular virtual port. The filter is called just before the frame is passed to the stack or application.  If the filter does not return Success, the incoming frame is silently discarded.

To add a receive filter to a virtual port on a MUX, add a global variable linked into the MUX's address space named __ghsentry_smmuxrxfilter_XXX where “XXX” is an arbitrary name that is unique to the filter being created.  The symbol must be of type struct muxfilter, and must contain configuration information for the filter.  It is important that the modifies field is set properly.  If it is not, it may lead to unintended modification of shared data, or waste of CPU cycles.  The following code creates a filter on port 0 of the MUX with id 10 that filters out all frames from a particular MAC address.  Since it does not modify the data the modifies is set to false.

static Error myfilter2(char *buf, int *len){

static char badaddr[] = { 0x00,0x01,0x03,0xD6,0x18,0xD7 };if(memcmp(buf+6, badaddr, 6) == 0) {

/* Frame came from disallowed sender. Destroy! */return Failure;

}return Success;

}struct muxfilter __ghsentry_smmuxrxfilter_a = { 10, 0, myfilter2, false };

02­05­2010. MUX doc version 1.10 10Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 11: ZCmux Guide 5010LOI Apr 15 2010

Complete MUX Configuration ExampleThe following must be placed in a location where it can be linked into the MUX's address space.

#include � mux/mux_config.h�

struct muxfilter{ int mux_id; int port; Error (*filter)(char *, int *); Boolean modifies;};

struct muxconfig __ghsentry_smmux_mux1 = { 1, "MUXEtherDev1", &mux_ethernet_driver_iod, 2, "__ghs_MUX1_buffers"

static Error demo_tx_filter(char *data, int *length){ static char destaddr[] = { 0x00,0x01,0x03,0xD6,0x18,0xD7 }; memcpy(data, destaddr, 6); return Success;}

struct muxfilter __ghsentry_smmuxtxfilter_a = {MUX1, 0, demo_tx_filter, true};

Advanced Features of the ZC­MUXThe ZC­MUX can be compiled with various macros to enable certain advanced features.  Change of any of these macros requires ZC­MUX source to recompile the MUX libraries.  The default values of these symbols are defined in sm_mux.h.  The default values may be overridden by defining them in default.gpj with the ­D option or in sm_mux.h.  These macros are described in the following section.

Global MUX Configuration MAX_ENET_MUXES – the maximum number of Ethernet MUXes allowed on the system.  If 

this number is too large, some physical memory will be wasted.  This number should be equal to the number of physical ports used for MUXes.

MAX_ENET_MUX_VDEVS – the cumulative maximum number of vports on all MUXes system­wide.  For example, for two MUXes, one with 3 vports and one with 6 vports, MAX_ENET_MUX_VDEVS must be at least 9.  If the number is too large, some physical memory will be wasted.

ENET_MUX_NUM_MAC_ADDR – the cumulative number of unique and multicast MAC addresses that can be assigned to a vport.  NOTE: A vport needs to always have at least one unique MAC address; it cannot be assigned only a multicast MAC address.  MAC addresses can be assigned with the MUXVport_clear_MAC(), MUXVport_add_MAC() and MUXVport_set_MAC() methods described below.    By default ENET_MUX_NUM_MAC_ADDR is 2.  

02­05­2010. MUX doc version 1.10 11Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 12: ZCmux Guide 5010LOI Apr 15 2010

MUX_GLOBAL_ACCESS – this greatly increases MUX performance by allowing all stacks unrestricted read access to MUX frame buffers.

MUX_DISABLE_CLEAR – this increases MUX performance by not clearing MUX frame buffers between uses, which is a potential security risk.

ENET_MUX_USE_MEMCPY – if defined, the MUX will use memcpy() for frames smaller than ENET_MUX_INIT_MEMCPY_LIMIT.  This may improve performance on CPUs with slow memory mapping operations.  ENET_MUX_INIT_MEMCPY_LIMIT may be tuned for optimal performance.  If MUX_GLOBAL_ACCESS is defined, this option is disabled.

ENET_MUX_BROADCAST_SHARED – if defined, improves MUX performance with broadcast frames, particularly with large numbers of vports.  However, this option uses a larger amount of fixed memory and may be slower for MUXes with only one or two vports.  If MUX_GLOBAL_ACCESS is defined, this option is disabled.

ghnetv1 TCPIP stack and the ZC­MUXghnetv1 ZC­MUX support has been deprecated in favor of ghnetv2

ghnetv2 TCPIP stack and the ZC­MUXTo attach a ghnetv2 TCP/IP stack to a vport, link the stack with the libmux_ethdriver and libvport libraries by adding the following to the stack's project (i.e. ip4server_modules.gpj):

­lvport

­lmux_ethdriver

The stack should be also linked with the appropriate stack library such as libip4.

Use of the libmux_ethdriver requires the definition of the __ghs_mux_vport_IDs struct which is used by the muxvport driver to attach TCP/IP stacks to various virtual ports.  A vport ID consist of a MUX ID and a vport number.  The pair{1, 2} signifies vport 2 on the MUX 1.  the __ghs_mux_vport_IDs sturct must end with {­1,­1} and should be placed in the address space of the TCPIP stack.  The following is an example of how to declare  __ghs_mux_vport_IDs:

typedef struct _vportID{ int mux_id; int vport_num;} vportID;

__ghs_mux_vport_IDs = {{1, 2},{-1,-1}}

An example of a ghnetv2 using the ZC­MUX can be found under:

 default.gpj­>examples.gpj­>networkexamples.gpj­>ip4servermux_example.gpj

02­05­2010. MUX doc version 1.10 12Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 13: ZCmux Guide 5010LOI Apr 15 2010

Link time memory for MUX (optional)Static memory needs to be set aside for the MUX and its vports.  By default the amount of memory reserved depends on macros the MAX_ENET_MUXES, and MAX_ENET_MUX_VDEVS (see Global MUX Configuration), which can only be set before compile time.  Because compile time may be too early to determine these values, the MUX allows memory to provided for it at link time.  To provide the MUX with link time memory, declare a variable named mux_alloc_linked of type struct mux_allocation.  At link time if a variable named mux_alloc_linked is declared, the MUX will use memory allocated by that variable, else it will default to memory reserved at compile time by the MAX_ENET_MUXES, and MAX_ENET_MUX_VDEVS macros.

struct mux_allocation can be found in mux_config.h and is defined as follows.

struct mux_allocation{ int num_muxes; mux_t *muxes;

int num_vports; mux_vport_t *vports;};

The num_muxes field should contain the max number of MUXes allocated for the MUX.  This is equivalent to setting a MAX_ENET_MUXES at compile time.  This should be the length of the muxes field.

The muxes field should contain a pointer to the memory allocated for for the MUXes.

The num_vports field should contain the max number of vports allocated for the MUX.  This is equivalent to MAX_ENET_MUX_VDEVS.  This should be the length of the vports field.

The vports field should contain a pointer to the memory allocated for for the vports.

The following is an example configuration:

#include "mux/mux_config.h"

#define LINKED_NUM_MUX 2#define LINKED_NUM_VPORT NUM_VPORTS 10

mux_t lmuxes[LINKED_NUM_MUX];mux_vport_t lvports[LINKED_NUM_VPORT];

struct mux_allocation mux_alloc_linked = { LINKED_NUM_MUX, lmuxes, LINKED_NUM_VPORT, lvports };

02­05­2010. MUX doc version 1.10 13Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 14: ZCmux Guide 5010LOI Apr 15 2010

ZC­MUX­vport APIThe following section describes the ZC­MUX­vport API that enables stacks or suitable applications to directly communicate with the MUX.  The ZC­MUX­vport API is also described in the comments in mux_vport.h.

A stack using the ZC­MUX­vport API should include the mux_vport.h header file by adding:#include <mux/mux_vport.h>

and be compiled with the library libvport by adding:-lvport

to the stack's project file.

Data typesMUXVportDev

This data type stores connection information associated with a particular vport on a particular MUX. It is passed as a argument in all methods in the ZC­MUX­vport API.  It is defined in mux/mux_vport.h and initialized via the method  MUXVport_connect().

Methods

Error MUXVport_connect(MUXVportDev *vportDev, int mux_id, int vportNum);

This method initializes the MUXVportDev  pointed to by vportDev.  This method associates the stack with vport vportNum on the MUX mux_id.  This method should be called prior to any other methods on the vport.

Error MUXVport_get_info(MUXVportDev *vportDev, Value *requiredMemory,Value *maxRxBufs, Value *maxTxBufs);

This method retrieves information about the vport necessary to complete stack initialization. requiredMemory returns the amount of Virtual Address Space memory (in bytes) required by the vport for transmit and receive frames.  maxTxBufs and maxRxBufs returns the maximum number of transmit and receive frames a stack can have outstanding before frames are dropped.  If a particular parameter is not needed by the stack, pass a NULL pointer.

Error MUXVport_map_memory_buffers(MUXVportDev *vportDev, MemoryRegion bufsMR Address *stackFirst);

This method gives the MemoryRegion bufsMR to the MUX to manage.  

For Virtual Address Space stacks the bufsMR must be a virtual MemoryRegion and must be at least requiredMemory (as returned from MUXVport_get_info()) bytes in length.  requiredMemory bytes will be split off from bufsMR and given to the MUX to manage.  Because the MUX takes control of this virtual MemoryRegion, any information about the MemoryRegion needed by the 

02­05­2010. MUX doc version 1.10 14Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 15: ZCmux Guide 5010LOI Apr 15 2010

stack (e.g., MemoryRegion's first and last Addresses) should be retrieved prior to the invocation of this method.  

For Kernel Space stacks the bufsMR should be set to NULLMemoryRegion (no mapping is done because the stack should have direct access to the physical memory).

stackFirst will return the Address location of the first frame in the stack's Address Space.  For Virtual Address Space stacks, this is generally the first Address of the of bufsMR MemoryRegion. For Kernel Space stacks, this is actual location of the first frame in physical memory.

Error MUXVport_get_semaphore(MUXVportDev *vportDev, Semaphore *notifySem);

This method returns the vport notification event semaphore.  When an event occurs, MUXVport_get_status() should be called to retrieve the event(s).  Multiple events can be merged into one semaphore release .  Events are described in MUXVport_get_status().

Error MUXVport_get_status(MUXVportDev *vportDev, Value *cause,Value *arg0, Value *arg1);

This method retrieves a pending notification event to be handled by the stack.  This method should be called upon a successful wait on the semaphore returned from MUXVport_get_semaphore(). Because multiple events can be merged into one semaphore release, this method should be called repeatedly until a cause of VPORT_STATUS_NONE is returned.  cause will return the type of event that has occurred.  arg0 and arg1 contain information dependent on the type of event.  The following are events types:

VPORT_STATUS_NONE – there are no pending events.  arg0 and arg1 will return 0.

VPORT_STATUS_READ_DONE – A receive frame has completed successfully.  arg0 will contain the frame index of where the receive frame.  arg1 will contain the length of valid data.

VPORT_STATUS_WRITE_DONE – A transmit frame has completed successfully.  arg0 will contain the frame index of the transmitted frame.  arg1 will contain the user_data transmitted with the frame (via MUXVport_tx()).

Error MUXVport_get_tx(MUXVportDev *vportDev, Value *frame_index);

This method requests a transmit frame.  Upon return of Success, the frame indexed by frame_index can be written to.  The frame is transmitted via MUXVport_tx().

Error MUXVport_tx(MUXVportDev *vportDev, Value frame_index, Value length, Value user_data);

This method transmits the frame indexed by frame_index.  A valid frame_index is be obtained via MUXVport_get_tx().  length is the number of valid bytes to transmit.  user_data is returned with the VPORT_STATUS_WRITE_DONE notification event.  The user_data parameter is provided for the 

02­05­2010. MUX doc version 1.10 15Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 16: ZCmux Guide 5010LOI Apr 15 2010

stack's convenience and is not used by the MUX (See MUXVport_get_status().)

Error MUXVport_rx_done(MUXVportDev *vportDev, Value frame_index);

This method returns an outstanding receive frame (obtained from VPORT_STATUS_READ_DONE notification event) to the MUX.  The stack needs to return receive frame in order to receive additional frames.

Error MUXVport_set_promiscuous(MUXVportDev *vportDev, Boolean mode);

This method sets the vport's promiscuous mode.  In promiscuous mode, a vport will receive all frames sent by any other port (physical or virtual).  Changes are immediate.

Error MUXVport_set_multicast(MUXVportDev *vportDev, Boolean capture);

This method sets the vport's multicast capture mode.  If capture is set then the vport will capture all multicast frames.  This is similar to promiscuous mode but for multicast frames only.  Changes are immediate.

Error MUXVport_get_MAC(MUXVportDev *vportDev, unsigned char const **mac_addr);

This method returns the vport's MAC address.

Error MUXVport_clear_MAC(MUXVportDev *vportDev);

This method clears the vport's MAC address buffer.  This method should be used in preparation to set the vport's MAC addresses.  Changes are not performed until MUXVport_set_MAC() is called.

Error MUXVport_add_MAC(MUXVportDev *vportDev, unsigned char *mac_addr);

This method adds a MAC address to the vport's recipient address buffer.  The number of MAC addresses that can be added is limited by the ENET_MUX_NUM_MAC_ADDR (see Global MUX Configuration). If the buffer is full, this method will return an Error.  Changes will not be performed until MUXVport_set_MAC() is called.

Error MUXVport_set_MAC(MUXVportDev *vportDev);

This method sets the vport to listen for any MAC addresses added via the MUXVport_add_MAC() method.  Changing of a vport's MAC address requires trio of MUXVport_clear_MAC(), MUXVport_add_MAC(), and MUXVport_set_MAC().s

02­05­2010. MUX doc version 1.10 16Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 17: ZCmux Guide 5010LOI Apr 15 2010

Error MUXVport_shutdown(MUXVportDev *vportDev);

This method will shutdown a vport; freeing resources.

Address MUXVport_frame_start(MUXVportDev *vportDev, frame_index);

This inline method will return the start address of a frame given a frame_index.  Frame index should have been obtained via MUXVport_get_tx() or MUXVport_get_status().

Stack Porting GuideThe following sections highlight differences between the Ethernet IODevice API and the ZC­MUX­vport API and offers hints on stack porting.  Provided sample code may be useful for building new stacks, as well as stack porting.  The format of this section will provide an example implementation using the Ethernet IODevice API and a corresponding implementation using the ZC­MUX­vport API.

High Level Differences between ZC­MUX and O­MUX

Without a high level understanding of the differences between the ZC­MUX and O­MUX, the porting may lead to no performance gain or worse performance.

A stack using the O­MUX uses the Ethernet IODevice API.  The Ethernet IODevice API allows two methods of transmitting and receiving of frames: Buffers and Blocks.  With the Buffer method, a stack provides valid Buffers in its Virtual Address Space to the Ethernet IODevice to transmit from or receive to.  With the Block method, a stack maps buffers into its Virtual Address Space and Ethernet IODevice provides buffer indexes for transmitting and receiving individual buffers.  Due to the implementation the O­MUX, both methods require an expensive memcpy() operation to transfer data to the between buffers.

The ZC­MUX avoids this expensive memcpy() operation by mapping buffers into a stack's Address Space.  The transmitting and receiving frames using the ZC­MUX­vport API is similar to the Ethernet IODevice Block method.  In both cases, memory is mapped1 directly into the stack's virtual address space and indexes are used to transmit or receive individual frame buffers.  The difference lies in the the index use.  The O­MUX uses “buffer” indexes to index into a buffer range dedicated to a particular Ethernet IODevice.  The ZC­MUX uses “frame” indexes to index into a frame range shared by all ports. Because of the similarities between the two, this porting guide will demonstrate how to port a stack from the Ethernet IODevice Block method to the ZC­MUX­vport API.

Vport InitializationA stack using the Ethernet IODevice API (Block method) would be required to prepare transmit and receive buffers before transmitting and receiving buffers.  The stack would be required to obtain the Ethernet IODevice Object from the ResourceManager, map the __ghs_tcpip_buffers physical 

1 Mapping is done by the MUX (as opposed to the stack) in the ZC­MUX for security reasons.02­05­2010. MUX doc version 1.10 17

Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.Green Hills Proprietary Information

Page 18: ZCmux Guide 5010LOI Apr 15 2010

MemoryRegion obtained from the ResourceManager, and calculate where the first buffer the Ethernet IODevice manages starts.  The stack requires the name of the of the Ethernet IODevice.  The following is sample code of how a stack may accomplish this:

/* This will store the address of the tcpip buffers block in this VAS */Address Buffers_First_Phy, Address Buffers_First_Virt;

/* These will store the first address of rx and tx buffers managed by this * device */Address Device_rx_Buffer_First_Phy, Address Device_tx_Buffer_First_Phy;Address Device_rx_Buffer_First_Virt, Address Device_tx_Buffer_First_Virt;

char *devName = "EtherDev2";MemoryRegion PhyMemReg;

static void Init(void){ MemoryRegion VirtMemReg; Value offset;

RequestResource((Object *)&ethiod, devName, "!systempassword")); /* Obtain the physical MemoryRegion for the tcpip buffers from the ResourceManager */ RequestResource((Object *)&PhyMemReg, "__ghs_tcpip_buffers",

"!systempassword");

GetMemoryRegionAddresses(PhyMemReg, &Buffers_First_Phy, NULL); /* Map tcpip buffers MemoryRegion into this VAS */ MapMemory(__ghs_VirtualMemoryRegionPool, PhyMemReg, &VirtMemReg,

&Buffers_First, NULL);

/* Calculate where the first rx buffer that this device manages */ ReadIODeviceRegister(ethiod->iod, IODEV_ETHERBUF_OFFSET, &offset); Device_rx_Buffer_First_Phy = Buffer_First_Phy + offset; Device_rx_Buffer_First_Virt = Buffer_First_Virt + offset;

/* Calculate where the first tx buffer that this device manages */ ReadIODeviceRegister(ethiod->iod, IODEV_ETHER_RXBUF, &num_rx_buffers); Device_tx_Buffer_First_Phy =

Buffer_First_Phy + offset + (INTEGRITY_ETH_BUF_SIZE * num_rx_buffers); Device_tx_Buffer_First_Virt =

Buffer_First_Virt + offset + (INTEGRITY_ETH_BUF_SIZE * num_rx_buffers);}

Likewise, a stack using the ZC­MUX­vport API must prepare transmit and receive buffers before transmitting and receiving frames.  A stack is required to initialize the vport connection, obtain information on memory requirements, and provide a MemoryRegion in its VAS for frames to be mapped to.  These are accomplished with the methods  MUXVport_connect(), MUXVport_get_info(), MUXVport_map_memory_buffers().  The stack requires the id of the MUX and the vport number to connect to.  The following is sample code of how a stack wishing to connect to vport 0 on MUX 1 may accomplish this:02­05­2010. MUX doc version 1.10 18

Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.Green Hills Proprietary Information

Page 19: ZCmux Guide 5010LOI Apr 15 2010

MUXVportDev vportDevice;int muxID = 1;int vportNum = 0;

/* This will store the address of the first frame. */Address Frames_First;

static Error Init(void){ MUXVportDev *vportDev = &vportDevice; Value reqMemSize; /* Connect to Vport */ MUXVport_connect(vportDev, muxID, vportNum);

/* Get information on vport requirements */ MUXVport_get_info(vportDev, &reqMemSize, NULL, NULL);

/* Make virtual MemoryRegion allocation of required size and give to vport/MUX */ AllocateAlignedMemoryRegion(__ghs_VirtualMemoryRegionPool,

reqMemSize, 12, &framesMR); MUXVport_map_memory_buffers(vportDev, framesMR, &Frames_First);

/* Cleanup and Close framesMR, control has been given to Vport/MUX */ CloseMemoryRegion(framesMR);}

Transmitting and Receiving Frames

Buffer and Frame IndexesA stack using the Block method uses buffer indexes to reference a memory location used for transmitting and receiving data.  Each buffer is of size INTEGRITY_ETH_BUF_SIZE and is indexed starting at the Ethernet IODevice's first receive and transmit buffers (in the previous example these would be Device_rx_Buffer_First_Virt and Device_tx_Buffer_First_Virt respectively).  A buffer with buffer index buffer_index would be memory starting at:

Device_rx_Buffer_First_Virt + (buffer_index * INTEGRITY_ETH_BUF_SIZE);

for rx buffers and:

Device_tx_Buffer_First_Virt + (buffer_index * INTEGRITY_ETH_BUF_SIZE);

for tx buffers.

Transmitting and receiving of frames using the ZC­MUX­vport API is accomplished by use of frame indexes.  A frame is a portion of memory indexed by a frame_index.  The application should determine the memory address referenced by the frame_index with MUXVport_frame_start().

02­05­2010. MUX doc version 1.10 19Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 20: ZCmux Guide 5010LOI Apr 15 2010

Transmitting FramesTo transmit a buffer, a stack using the Block method is required to obtain a transmit buffer index via ReadStatusFromIODevice(), write to the corresponding buffer, and make a request to transmit that buffer via WriteSubBlockToIODevice().  The following sample code shows this may be accomplished:

/* Assume mac_addr points to this devices MAC address */char *mac_addr;

void writeEmptyBroadCast(IODevice iod, int length){ Address phy_buffer; char *buffer;

/* obtain a buffer */ ReadIODeviceStatus(iod, IODEV_STAT_GENERIC, &buffer_index, 4);

phy_buffer = (Device_tx_Buffer_First_Phy + (buffer_index * INTEGRITY_ETH_BUF_SIZE));

buffer = (char *) (Device_tx_Buffer_First_Virt + (buffer_index * INTEGRITY_ETH_BUF_SIZE));

/* Use the buffer */ memset(buffer, 0xff, 6); memcpy(buffer + 6, mac_addr, 6); memset(buffer + 12, 0, length - 12);

WriteSubBlockToIODevice(iod, length, buffer_index, PhyMemReg, phy_buffer, length);

}

To transmit a frame, a stack using the ZC­MUX­vport API is required to obtain a transmit frame index via MUXVport_get_tx(), write to the corresponding frame, and make a request to transmit that frame via MUXVport_tx().  The following sample code shows how this may be accomplished:

/* Assume mac_addr points to this devices MAC address */char *mac_addr;

void writeEmptyBroadCast(MUXVportDev *vportDev, int length){ Value tx_index; unsigned char *frame;

/* obtain a buffer */ MUXVport_get_tx(vportDev, &tx_index); /* Use the buffer */ frame = (unsigned char *)MUXVport_frame_start(vportDev, tx_index); memset(&frame[0], 0xff, 6); memcpy(&frame[6], mac_addr, 6); memset(&frame[12], 0, length - 12);

02­05­2010. MUX doc version 1.10 20Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 21: ZCmux Guide 5010LOI Apr 15 2010

MUXVport_tx(vportDev, tx_index, length, 0);}

Receiving Frames (Preparation)To receive a frame, a stack using the Ethernet IODevice API (Block method) is required to notify the Ethernet IODevice that the BSP's Ethernet buffer ring should be posted to the device for reading via ReadSubBlockFromIODevice().  The following sample code shows how this may be accomplished:

static void start_rx(IODevice iod){ int i; Value num_rx_bufs;

/* Figure out how many buffers to receive */ ReadIODeviceRegister(iod, IODEV_ETHER_RXBUF, &num_rx_bufs);

/* Do the initial receives on the device */ for (i=0; i < num_rx_bufs; i++) {

Address rxBufAddr = (Device_tx_Buffer_First_Phy +(i * INTEGRITY_ETH_BUF_SIZE));

ReadSubBlockFromIODevice(ethiod->iod, 0, i, PhyMemReg,rxBufAddr, INTEGRITY_ETH_BUF_SIZE);

}}

A stack using the ZC­MUX­vport API does not need to prep the vport for receiving frames.  Frames will begin to come in as soon as the vport is initialized.

Event HandlingEvent handling between the Ethernet IODevice API and the ZC­MUX­vport API is very similar.  In the case of the Ethernet IODevice, the stack waits on the Ethernet IODevice Object and obtains the status via ReadIODeviceStatus().  The stack should read the status until a status of NoPendingInterrupt is received.  If the event was a ReadBlockComplete, the stack needs to re­receive on the buffer via a call to ReadSubBlockFromIODevice() when it is finished with the buffer.  The following is an example event handler for the Ethernet IODevice API (Block method):

buffer_index = status.Id; switch(status.Cause){

case ReadBlockCompleted:

/* Code for receive of buffer */ ...

/* Re-receive on buffer */ ReadBuffersFromIODevice(ethiod, 0, id, &rxBuffer[id]); break;

02­05­2010. MUX doc version 1.10 21Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 22: ZCmux Guide 5010LOI Apr 15 2010

case WriteBlockCompleted:

/* Code for transmit complete. */ ... break;

case NoPendingInterrupt: break;

}}while(status.Cause != NoPendingInterrupt);

}}

The structure of the event handler using the ZC­MUX­vport API is nearly identical.  The differences are that the stack uses a Semaphore, MUXVport_get_status() is used to obtain the status and MUXVport_rx_done() should be called when the stack is finished with the frame.  The following is an example event handler for the ZC­MUX­vport API.

static void event_handler(MUXVportDev *vportDev){ int buffer_index; Semaphore notifySem; Value cause, arg0, arg1; MUXVport_get_semaphore(vportDev, &notifySem); while(1){

/* Wait for Event */WaitForSemaphore(notifySem);

do{ MUXVport_get_status(vportDev, &cause, &arg0, &arg1); buffer_index = status.Id; switch(cause){

case VPORT_STATUS_READ_DONE:

/* Code for handling receive of frame */ ...

/* Re-receive on frame */ MUXVport_rx_done(vportDev, arg0); break;

case VPORT_STATUS_WRITE_DONE:

/* Code for handling transmit complete. */ ... break;

case VPORT_STATUS_NONE: break;

}}while(cause != VPORT_STATUS_NONE);

}

02­05­2010. MUX doc version 1.10 22Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information

Page 23: ZCmux Guide 5010LOI Apr 15 2010

}

02­05­2010. MUX doc version 1.10 23Copyright (c) 2010, Green Hills Software, Inc., all rights reserved.

Green Hills Proprietary Information