2976 lines
		
	
	
	
		
			102 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			2976 lines
		
	
	
	
		
			102 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright 2010 Tilera Corporation. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *   This program is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								 *   modify it under the terms of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 *   as published by the Free Software Foundation, version 2.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *   This program is distributed in the hope that it will be useful, but
							 | 
						||
| 
								 | 
							
								 *   WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
							 | 
						||
| 
								 | 
							
								 *   NON INFRINGEMENT.  See the GNU General Public License for
							 | 
						||
| 
								 | 
							
								 *   more details.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * NetIO interface structures and macros.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __NETIO_INTF_H__
							 | 
						||
| 
								 | 
							
								#define __NETIO_INTF_H__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <hv/netio_errors.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __KERNEL__
							 | 
						||
| 
								 | 
							
								#include <linux/types.h>
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#include <stdint.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if !defined(__HV__) && !defined(__BOGUX__) && !defined(__KERNEL__)
							 | 
						||
| 
								 | 
							
								#include <assert.h>
							 | 
						||
| 
								 | 
							
								#define netio_assert assert  /**< Enable assertions from macros */
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#define netio_assert(...) ((void)(0))  /**< Disable assertions from macros */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * If none of these symbols are defined, we're building libnetio in an
							 | 
						||
| 
								 | 
							
								 * environment where we have pthreads, so we'll enable locking.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#if !defined(__HV__) && !defined(__BOGUX__) && !defined(__KERNEL__) && \
							 | 
						||
| 
								 | 
							
								    !defined(__NEWLIB__)
							 | 
						||
| 
								 | 
							
								#define _NETIO_PTHREAD       /**< Include a mutex in netio_queue_t below */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * If NETIO_UNLOCKED is defined, we don't do use per-cpu locks on
							 | 
						||
| 
								 | 
							
								 * per-packet NetIO operations.  We still do pthread locking on things
							 | 
						||
| 
								 | 
							
								 * like netio_input_register, though.  This is used for building
							 | 
						||
| 
								 | 
							
								 * libnetio_unlocked.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#ifndef NETIO_UNLOCKED
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Avoid PLT overhead by using our own inlined per-cpu lock. */
							 | 
						||
| 
								 | 
							
								#include <sched.h>
							 | 
						||
| 
								 | 
							
								typedef int _netio_percpu_mutex_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __inline int
							 | 
						||
| 
								 | 
							
								_netio_percpu_mutex_init(_netio_percpu_mutex_t* lock)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  *lock = 0;
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __inline int
							 | 
						||
| 
								 | 
							
								_netio_percpu_mutex_lock(_netio_percpu_mutex_t* lock)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  while (__builtin_expect(__insn_tns(lock), 0))
							 | 
						||
| 
								 | 
							
								    sched_yield();
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __inline int
							 | 
						||
| 
								 | 
							
								_netio_percpu_mutex_unlock(_netio_percpu_mutex_t* lock)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  *lock = 0;
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else /* NETIO_UNLOCKED */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Don't do any locking for per-packet NetIO operations. */
							 | 
						||
| 
								 | 
							
								typedef int _netio_percpu_mutex_t;
							 | 
						||
| 
								 | 
							
								#define _netio_percpu_mutex_init(L)
							 | 
						||
| 
								 | 
							
								#define _netio_percpu_mutex_lock(L)
							 | 
						||
| 
								 | 
							
								#define _netio_percpu_mutex_unlock(L)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* NETIO_UNLOCKED */
							 | 
						||
| 
								 | 
							
								#endif /* !__HV__, !__BOGUX, !__KERNEL__, !__NEWLIB__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** How many tiles can register for a given queue.
							 | 
						||
| 
								 | 
							
								 *  @ingroup setup */
							 | 
						||
| 
								 | 
							
								#define NETIO_MAX_TILES_PER_QUEUE  64
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Largest permissible queue identifier.
							 | 
						||
| 
								 | 
							
								 *  @ingroup setup  */
							 | 
						||
| 
								 | 
							
								#define NETIO_MAX_QUEUE_ID        255
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Metadata packet checksum/ethertype flags. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The L4 checksum has not been calculated. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NO_L4_CSUM_SHIFT           0
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NO_L4_CSUM_RMASK           1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NO_L4_CSUM_MASK \
							 | 
						||
| 
								 | 
							
								         (_NETIO_PKT_NO_L4_CSUM_RMASK << _NETIO_PKT_NO_L4_CSUM_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The L3 checksum has not been calculated. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NO_L3_CSUM_SHIFT           1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NO_L3_CSUM_RMASK           1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NO_L3_CSUM_MASK \
							 | 
						||
| 
								 | 
							
								         (_NETIO_PKT_NO_L3_CSUM_RMASK << _NETIO_PKT_NO_L3_CSUM_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The L3 checksum is incorrect (or perhaps has not been calculated). */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BAD_L3_CSUM_SHIFT          2
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BAD_L3_CSUM_RMASK          1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BAD_L3_CSUM_MASK \
							 | 
						||
| 
								 | 
							
								         (_NETIO_PKT_BAD_L3_CSUM_RMASK << _NETIO_PKT_BAD_L3_CSUM_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The Ethernet packet type is unrecognized. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TYPE_UNRECOGNIZED_SHIFT    3
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TYPE_UNRECOGNIZED_RMASK    1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TYPE_UNRECOGNIZED_MASK \
							 | 
						||
| 
								 | 
							
								         (_NETIO_PKT_TYPE_UNRECOGNIZED_RMASK << \
							 | 
						||
| 
								 | 
							
								          _NETIO_PKT_TYPE_UNRECOGNIZED_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Metadata packet type flags. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Where the packet type bits are; this field is the index into
							 | 
						||
| 
								 | 
							
								 *  _netio_pkt_info. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TYPE_SHIFT        4
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TYPE_RMASK        0x3F
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** How many VLAN tags the packet has, and, if we have two, which one we
							 | 
						||
| 
								 | 
							
								 *  actually grouped on.  A VLAN within a proprietary (Marvell or Broadcom)
							 | 
						||
| 
								 | 
							
								 *  tag is counted here. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_SHIFT        4
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_RMASK        0x3
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_MASK \
							 | 
						||
| 
								 | 
							
								         (_NETIO_PKT_VLAN_RMASK << _NETIO_PKT_VLAN_SHIFT)
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_NONE         0   /* No VLAN tag. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_ONE          1   /* One VLAN tag. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_TWO_OUTER    2   /* Two VLAN tags, outer one used. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_VLAN_TWO_INNER    3   /* Two VLAN tags, inner one used. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Which proprietary tags the packet has. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_SHIFT         6
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_RMASK         0x3
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_MASK \
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_TAG_RMASK << _NETIO_PKT_TAG_SHIFT)
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_NONE          0   /* No proprietary tags. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_MRVL          1   /* Marvell HyperG.Stack tags. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_MRVL_EXT      2   /* HyperG.Stack extended tags. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_TAG_BRCM          3   /* Broadcom HiGig tags. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Whether a packet has an LLC + SNAP header. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_SNAP_SHIFT        8
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_SNAP_RMASK        0x1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_SNAP_MASK \
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_SNAP_RMASK << _NETIO_PKT_SNAP_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* NOTE: Bits 9 and 10 are unused. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Length of any custom data before the L2 header, in words. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_CUSTOM_LEN_SHIFT  11
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_CUSTOM_LEN_RMASK  0x1F
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_CUSTOM_LEN_MASK \
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_CUSTOM_LEN_RMASK << _NETIO_PKT_CUSTOM_LEN_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The L4 checksum is incorrect (or perhaps has not been calculated). */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BAD_L4_CSUM_SHIFT 16
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BAD_L4_CSUM_RMASK 0x1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BAD_L4_CSUM_MASK \
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_BAD_L4_CSUM_RMASK << _NETIO_PKT_BAD_L4_CSUM_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Length of the L2 header, in words. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_L2_LEN_SHIFT  17
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_L2_LEN_RMASK  0x1F
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_L2_LEN_MASK \
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_L2_LEN_RMASK << _NETIO_PKT_L2_LEN_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Flags in minimal packet metadata. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** We need an eDMA checksum on this packet. */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NEED_EDMA_CSUM_SHIFT            0
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NEED_EDMA_CSUM_RMASK            1
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_NEED_EDMA_CSUM_MASK \
							 | 
						||
| 
								 | 
							
								         (_NETIO_PKT_NEED_EDMA_CSUM_RMASK << _NETIO_PKT_NEED_EDMA_CSUM_SHIFT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Data within the packet information table. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Note that, for efficiency, code which uses these fields assumes that none
							 | 
						||
| 
								 | 
							
								 * of the shift values below are zero.  See uses below for an explanation. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Offset within the L2 header of the innermost ethertype (in halfwords). */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_INFO_ETYPE_SHIFT       6
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_INFO_ETYPE_RMASK    0x1F
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Offset within the L2 header of the VLAN tag (in halfwords). */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_INFO_VLAN_SHIFT       11
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_INFO_VLAN_RMASK     0x1F
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The size of a memory buffer representing a small packet.
							 | 
						||
| 
								 | 
							
								 *  @ingroup egress */
							 | 
						||
| 
								 | 
							
								#define SMALL_PACKET_SIZE 256
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The size of a memory buffer representing a large packet.
							 | 
						||
| 
								 | 
							
								 *  @ingroup egress */
							 | 
						||
| 
								 | 
							
								#define LARGE_PACKET_SIZE 2048
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The size of a memory buffer representing a jumbo packet.
							 | 
						||
| 
								 | 
							
								 *  @ingroup egress */
							 | 
						||
| 
								 | 
							
								#define JUMBO_PACKET_SIZE (12 * 1024)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Common ethertypes.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress */
							 | 
						||
| 
								 | 
							
								/** @{ */
							 | 
						||
| 
								 | 
							
								/** The ethertype of IPv4. */
							 | 
						||
| 
								 | 
							
								#define ETHERTYPE_IPv4 (0x0800)
							 | 
						||
| 
								 | 
							
								/** The ethertype of ARP. */
							 | 
						||
| 
								 | 
							
								#define ETHERTYPE_ARP (0x0806)
							 | 
						||
| 
								 | 
							
								/** The ethertype of VLANs. */
							 | 
						||
| 
								 | 
							
								#define ETHERTYPE_VLAN (0x8100)
							 | 
						||
| 
								 | 
							
								/** The ethertype of a Q-in-Q header. */
							 | 
						||
| 
								 | 
							
								#define ETHERTYPE_Q_IN_Q (0x9100)
							 | 
						||
| 
								 | 
							
								/** The ethertype of IPv6. */
							 | 
						||
| 
								 | 
							
								#define ETHERTYPE_IPv6 (0x86DD)
							 | 
						||
| 
								 | 
							
								/** The ethertype of MPLS. */
							 | 
						||
| 
								 | 
							
								#define ETHERTYPE_MPLS (0x8847)
							 | 
						||
| 
								 | 
							
								/** @} */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** The possible return values of NETIO_PKT_STATUS.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef enum
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /** No problems were detected with this packet. */
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_STATUS_OK,
							 | 
						||
| 
								 | 
							
								  /** The packet is undersized; this is expected behavior if the packet's
							 | 
						||
| 
								 | 
							
								    * ethertype is unrecognized, but otherwise the packet is likely corrupt. */
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_STATUS_UNDERSIZE,
							 | 
						||
| 
								 | 
							
								  /** The packet is oversized and some trailing bytes have been discarded.
							 | 
						||
| 
								 | 
							
								      This is expected behavior for short packets, since it's impossible to
							 | 
						||
| 
								 | 
							
								      precisely determine the amount of padding which may have been added to
							 | 
						||
| 
								 | 
							
								      them to make them meet the minimum Ethernet packet size. */
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_STATUS_OVERSIZE,
							 | 
						||
| 
								 | 
							
								  /** The packet was judged to be corrupt by hardware (for instance, it had
							 | 
						||
| 
								 | 
							
								      a bad CRC, or part of it was discarded due to lack of buffer space in
							 | 
						||
| 
								 | 
							
								      the I/O shim) and should be discarded. */
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_STATUS_BAD
							 | 
						||
| 
								 | 
							
								} netio_pkt_status_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Log2 of how many buckets we have. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LOG2_NUM_BUCKETS (10)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** How many buckets we have.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress */
							 | 
						||
| 
								 | 
							
								#define NETIO_NUM_BUCKETS (1 << NETIO_LOG2_NUM_BUCKETS)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief A group-to-bucket identifier.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup setup
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This tells us what to do with a given group.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef union {
							 | 
						||
| 
								 | 
							
								  /** The header broken down into bits. */
							 | 
						||
| 
								 | 
							
								  struct {
							 | 
						||
| 
								 | 
							
								    /** Whether we should balance on L4, if available */
							 | 
						||
| 
								 | 
							
								    unsigned int __balance_on_l4:1;
							 | 
						||
| 
								 | 
							
								    /** Whether we should balance on L3, if available */
							 | 
						||
| 
								 | 
							
								    unsigned int __balance_on_l3:1;
							 | 
						||
| 
								 | 
							
								    /** Whether we should balance on L2, if available */
							 | 
						||
| 
								 | 
							
								    unsigned int __balance_on_l2:1;
							 | 
						||
| 
								 | 
							
								    /** Reserved for future use */
							 | 
						||
| 
								 | 
							
								    unsigned int __reserved:1;
							 | 
						||
| 
								 | 
							
								    /** The base bucket to use to send traffic */
							 | 
						||
| 
								 | 
							
								    unsigned int __bucket_base:NETIO_LOG2_NUM_BUCKETS;
							 | 
						||
| 
								 | 
							
								    /** The mask to apply to the balancing value. This must be one less
							 | 
						||
| 
								 | 
							
								     * than a power of two, e.g. 0x3 or 0xFF.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    unsigned int __bucket_mask:NETIO_LOG2_NUM_BUCKETS;
							 | 
						||
| 
								 | 
							
								    /** Pad to 32 bits */
							 | 
						||
| 
								 | 
							
								    unsigned int __padding:(32 - 4 - 2 * NETIO_LOG2_NUM_BUCKETS);
							 | 
						||
| 
								 | 
							
								  } bits;
							 | 
						||
| 
								 | 
							
								  /** To send out the IDN. */
							 | 
						||
| 
								 | 
							
								  unsigned int word;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_group_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief A VLAN-to-bucket identifier.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup setup
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This tells us what to do with a given VLAN.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef netio_group_t netio_vlan_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * A bucket-to-queue mapping.
							 | 
						||
| 
								 | 
							
								 * @ingroup setup
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef unsigned char netio_bucket_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * A packet size can always fit in a netio_size_t.
							 | 
						||
| 
								 | 
							
								 * @ingroup setup
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef unsigned int netio_size_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief Ethernet standard (ingress) packet metadata.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This is additional data associated with each packet.
							 | 
						||
| 
								 | 
							
								 * This structure is opaque and accessed through the @ref ingress.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Also, the buffer population operation currently assumes that standard
							 | 
						||
| 
								 | 
							
								 * metadata is at least as large as minimal metadata, and will need to be
							 | 
						||
| 
								 | 
							
								 * modified if that is no longer the case.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								  /** This structure is opaque. */
							 | 
						||
| 
								 | 
							
								  unsigned char opaque[24];
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  /** The overall ordinal of the packet */
							 | 
						||
| 
								 | 
							
								  unsigned int __packet_ordinal;
							 | 
						||
| 
								 | 
							
								  /** The ordinal of the packet within the group */
							 | 
						||
| 
								 | 
							
								  unsigned int __group_ordinal;
							 | 
						||
| 
								 | 
							
								  /** The best flow hash IPP could compute. */
							 | 
						||
| 
								 | 
							
								  unsigned int __flow_hash;
							 | 
						||
| 
								 | 
							
								  /** Flags pertaining to checksum calculation, packet type, etc. */
							 | 
						||
| 
								 | 
							
								  unsigned int __flags;
							 | 
						||
| 
								 | 
							
								  /** The first word of "user data". */
							 | 
						||
| 
								 | 
							
								  unsigned int __user_data_0;
							 | 
						||
| 
								 | 
							
								  /** The second word of "user data". */
							 | 
						||
| 
								 | 
							
								  unsigned int __user_data_1;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_pkt_metadata_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** To ensure that the L3 header is aligned mod 4, the L2 header should be
							 | 
						||
| 
								 | 
							
								 * aligned mod 4 plus 2, since every supported L2 header is 4n + 2 bytes
							 | 
						||
| 
								 | 
							
								 * long.  The standard way to do this is to simply add 2 bytes of padding
							 | 
						||
| 
								 | 
							
								 * before the L2 header.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_PACKET_PADDING 2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief Ethernet minimal (egress) packet metadata.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This structure represents information about packets which have
							 | 
						||
| 
								 | 
							
								 * been processed by @ref netio_populate_buffer() or
							 | 
						||
| 
								 | 
							
								 * @ref netio_populate_prepend_buffer().  This structure is opaque
							 | 
						||
| 
								 | 
							
								 * and accessed through the @ref egress.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @internal This structure is actually copied into the memory used by
							 | 
						||
| 
								 | 
							
								 * standard metadata, which is assumed to be large enough.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								  /** This structure is opaque. */
							 | 
						||
| 
								 | 
							
								  unsigned char opaque[14];
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  /** The offset of the L2 header from the start of the packet data. */
							 | 
						||
| 
								 | 
							
								  unsigned short l2_offset;
							 | 
						||
| 
								 | 
							
								  /** The offset of the L3 header from the start of the packet data. */
							 | 
						||
| 
								 | 
							
								  unsigned short l3_offset;
							 | 
						||
| 
								 | 
							
								  /** Where to write the checksum. */
							 | 
						||
| 
								 | 
							
								  unsigned char csum_location;
							 | 
						||
| 
								 | 
							
								  /** Where to start checksumming from. */
							 | 
						||
| 
								 | 
							
								  unsigned char csum_start;
							 | 
						||
| 
								 | 
							
								  /** Flags pertaining to checksum calculation etc. */
							 | 
						||
| 
								 | 
							
								  unsigned short flags;
							 | 
						||
| 
								 | 
							
								  /** The L2 length of the packet. */
							 | 
						||
| 
								 | 
							
								  unsigned short l2_length;
							 | 
						||
| 
								 | 
							
								  /** The checksum with which to seed the checksum generator. */
							 | 
						||
| 
								 | 
							
								  unsigned short csum_seed;
							 | 
						||
| 
								 | 
							
								  /** How much to checksum. */
							 | 
						||
| 
								 | 
							
								  unsigned short csum_length;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_pkt_minimal_metadata_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief An I/O notification header.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This is the first word of data received from an I/O shim in a notification
							 | 
						||
| 
								 | 
							
								 * packet. It contains framing and status information.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef union
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  unsigned int word; /**< The whole word. */
							 | 
						||
| 
								 | 
							
								  /** The various fields. */
							 | 
						||
| 
								 | 
							
								  struct
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    unsigned int __channel:7;    /**< Resource channel. */
							 | 
						||
| 
								 | 
							
								    unsigned int __type:4;       /**< Type. */
							 | 
						||
| 
								 | 
							
								    unsigned int __ack:1;        /**< Whether an acknowledgement is needed. */
							 | 
						||
| 
								 | 
							
								    unsigned int __reserved:1;   /**< Reserved. */
							 | 
						||
| 
								 | 
							
								    unsigned int __protocol:1;   /**< A protocol-specific word is added. */
							 | 
						||
| 
								 | 
							
								    unsigned int __status:2;     /**< Status of the transfer. */
							 | 
						||
| 
								 | 
							
								    unsigned int __framing:2;    /**< Framing of the transfer. */
							 | 
						||
| 
								 | 
							
								    unsigned int __transfer_size:14; /**< Transfer size in bytes (total). */
							 | 
						||
| 
								 | 
							
								  } bits;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								__netio_pkt_notif_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Returns the base address of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_HANDLE_BASE(p) \
							 | 
						||
| 
								 | 
							
								  ((unsigned char*)((p).word & 0xFFFFFFC0))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Returns the base address of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define _NETIO_PKT_BASE(p) \
							 | 
						||
| 
								 | 
							
								  _NETIO_PKT_HANDLE_BASE(p->__packet)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief An I/O notification packet (second word)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This is the second word of data received from an I/O shim in a notification
							 | 
						||
| 
								 | 
							
								 * packet.  This is the virtual address of the packet buffer, plus some flag
							 | 
						||
| 
								 | 
							
								 * bits.  (The virtual address of the packet is always 256-byte aligned so we
							 | 
						||
| 
								 | 
							
								 * have room for 8 bits' worth of flags in the low 8 bits.)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @internal
							 | 
						||
| 
								 | 
							
								 * NOTE: The low two bits must contain "__queue", so the "packet size"
							 | 
						||
| 
								 | 
							
								 * (SIZE_SMALL, SIZE_LARGE, or SIZE_JUMBO) can be determined quickly.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * If __addr or __offset are moved, _NETIO_PKT_BASE
							 | 
						||
| 
								 | 
							
								 * (defined right below this) must be changed.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef union
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  unsigned int word; /**< The whole word. */
							 | 
						||
| 
								 | 
							
								  /** The various fields. */
							 | 
						||
| 
								 | 
							
								  struct
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    /** Which queue the packet will be returned to once it is sent back to
							 | 
						||
| 
								 | 
							
								        the IPP.  This is one of the SIZE_xxx values. */
							 | 
						||
| 
								 | 
							
								    unsigned int __queue:2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** The IPP handle of the sending IPP. */
							 | 
						||
| 
								 | 
							
								    unsigned int __ipp_handle:2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Reserved for future use. */
							 | 
						||
| 
								 | 
							
								    unsigned int __reserved:1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** If 1, this packet has minimal (egress) metadata; otherwise, it
							 | 
						||
| 
								 | 
							
								        has standard (ingress) metadata. */
							 | 
						||
| 
								 | 
							
								    unsigned int __minimal:1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Offset of the metadata within the packet.  This value is multiplied
							 | 
						||
| 
								 | 
							
								     *  by 64 and added to the base packet address to get the metadata
							 | 
						||
| 
								 | 
							
								     *  address.  Note that this field is aligned within the word such that
							 | 
						||
| 
								 | 
							
								     *  you can easily extract the metadata address with a 26-bit mask. */
							 | 
						||
| 
								 | 
							
								    unsigned int __offset:2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** The top 24 bits of the packet's virtual address. */
							 | 
						||
| 
								 | 
							
								    unsigned int __addr:24;
							 | 
						||
| 
								 | 
							
								  } bits;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								__netio_pkt_handle_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* !__DOXYGEN__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief A handle for an I/O packet's storage.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * netio_pkt_handle_t encodes the concept of a ::netio_pkt_t with its
							 | 
						||
| 
								 | 
							
								 * packet metadata removed.  It is a much smaller type that exists to
							 | 
						||
| 
								 | 
							
								 * facilitate applications where the full ::netio_pkt_t type is too
							 | 
						||
| 
								 | 
							
								 * large, such as those that cache enormous numbers of packets or wish
							 | 
						||
| 
								 | 
							
								 * to transmit packet descriptors over the UDN.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Because there is no metadata, most ::netio_pkt_t operations cannot be
							 | 
						||
| 
								 | 
							
								 * performed on a netio_pkt_handle_t.  It supports only
							 | 
						||
| 
								 | 
							
								 * netio_free_handle() (to free the buffer) and
							 | 
						||
| 
								 | 
							
								 * NETIO_PKT_CUSTOM_DATA_H() (to access a pointer to its contents).
							 | 
						||
| 
								 | 
							
								 * The application must acquire any additional metadata it wants from the
							 | 
						||
| 
								 | 
							
								 * original ::netio_pkt_t and record it separately.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * A netio_pkt_handle_t can be extracted from a ::netio_pkt_t by calling
							 | 
						||
| 
								 | 
							
								 * NETIO_PKT_HANDLE().  An invalid handle (analogous to NULL) can be
							 | 
						||
| 
								 | 
							
								 * created by assigning the value ::NETIO_PKT_HANDLE_NONE. A handle can
							 | 
						||
| 
								 | 
							
								 * be tested for validity with NETIO_PKT_HANDLE_IS_VALID().
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  unsigned int word; /**< Opaque bits. */
							 | 
						||
| 
								 | 
							
								} netio_pkt_handle_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief A packet descriptor.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This data structure represents a packet.  The structure is manipulated
							 | 
						||
| 
								 | 
							
								 * through the @ref ingress and the @ref egress.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * While the contents of a netio_pkt_t are opaque, the structure itself is
							 | 
						||
| 
								 | 
							
								 * portable.  This means that it may be shared between all tiles which have
							 | 
						||
| 
								 | 
							
								 * done a netio_input_register() call for the interface on which the pkt_t
							 | 
						||
| 
								 | 
							
								 * was initially received (via netio_get_packet()) or retrieved (via
							 | 
						||
| 
								 | 
							
								 * netio_get_buffer()).  The contents of a netio_pkt_t can be transmitted to
							 | 
						||
| 
								 | 
							
								 * another tile via shared memory, or via a UDN message, or by other means.
							 | 
						||
| 
								 | 
							
								 * The destination tile may then use the pkt_t as if it had originally been
							 | 
						||
| 
								 | 
							
								 * received locally; it may read or write the packet's data, read its
							 | 
						||
| 
								 | 
							
								 * metadata, free the packet, send the packet, transfer the netio_pkt_t to
							 | 
						||
| 
								 | 
							
								 * yet another tile, and so forth.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Once a netio_pkt_t has been transferred to a second tile, the first tile
							 | 
						||
| 
								 | 
							
								 * should not reference the original copy; in particular, if more than one
							 | 
						||
| 
								 | 
							
								 * tile frees or sends the same netio_pkt_t, the IPP's packet free lists will
							 | 
						||
| 
								 | 
							
								 * become corrupted.  Note also that each tile which reads or modifies
							 | 
						||
| 
								 | 
							
								 * packet data must obey the memory coherency rules outlined in @ref input.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								  /** This structure is opaque. */
							 | 
						||
| 
								 | 
							
								  unsigned char opaque[32];
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  /** For an ingress packet (one with standard metadata), this is the
							 | 
						||
| 
								 | 
							
								   *  notification header we got from the I/O shim.  For an egress packet
							 | 
						||
| 
								 | 
							
								   *  (one with minimal metadata), this word is zero if the packet has not
							 | 
						||
| 
								 | 
							
								   *  been populated, and nonzero if it has. */
							 | 
						||
| 
								 | 
							
								  __netio_pkt_notif_t __notif_header;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Virtual address of the packet buffer, plus state flags. */
							 | 
						||
| 
								 | 
							
								  __netio_pkt_handle_t __packet;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Metadata associated with the packet. */
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t __metadata;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_pkt_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_NOTIF_HEADER(pkt) ((pkt)->__notif_header)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_IPP_HANDLE(pkt) ((pkt)->__packet.bits.__ipp_handle)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_QUEUE(pkt) ((pkt)->__packet.bits.__queue)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_NOTIF_HEADER_M(mda, pkt) ((pkt)->__notif_header)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_IPP_HANDLE_M(mda, pkt) ((pkt)->__packet.bits.__ipp_handle)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_MINIMAL(pkt) ((pkt)->__packet.bits.__minimal)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_QUEUE_M(mda, pkt) ((pkt)->__packet.bits.__queue)
							 | 
						||
| 
								 | 
							
								#define __NETIO_PKT_FLAGS_M(mda, pkt) ((mda)->__flags)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Packet information table, used by the attribute access functions below. */
							 | 
						||
| 
								 | 
							
								extern const uint16_t _netio_pkt_info[];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* __DOXYGEN__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								/* These macros are deprecated and will disappear in a future MDE release. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PKT_GOOD_CHECKSUM(pkt) \
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_L4_CSUM_CORRECT(pkt)
							 | 
						||
| 
								 | 
							
								#define NETIO_PKT_GOOD_CHECKSUM_M(mda, pkt) \
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_L4_CSUM_CORRECT_M(mda, pkt)
							 | 
						||
| 
								 | 
							
								#endif /* __DOXYGEN__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Packet attribute access functions. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the metadata for a packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Calling this function once and passing the result to other retrieval
							 | 
						||
| 
								 | 
							
								 * functions with a "_M" suffix usually improves performance.  This
							 | 
						||
| 
								 | 
							
								 * function must be called on an 'ingress' packet (i.e. one retrieved
							 | 
						||
| 
								 | 
							
								 * by @ref netio_get_packet(), on which @ref netio_populate_buffer() or
							 | 
						||
| 
								 | 
							
								 * @ref netio_populate_prepend_buffer have not been called). Use of this
							 | 
						||
| 
								 | 
							
								 * function on an 'egress' packet will cause an assertion failure.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to the packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_pkt_metadata_t*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_assert(!pkt->__packet.bits.__minimal);
							 | 
						||
| 
								 | 
							
								  return &pkt->__metadata;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the minimal metadata for a packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Calling this function once and passing the result to other retrieval
							 | 
						||
| 
								 | 
							
								 * functions with a "_MM" suffix usually improves performance.  This
							 | 
						||
| 
								 | 
							
								 * function must be called on an 'egress' packet (i.e. one on which
							 | 
						||
| 
								 | 
							
								 * @ref netio_populate_buffer() or @ref netio_populate_prepend_buffer()
							 | 
						||
| 
								 | 
							
								 * have been called, or one retrieved by @ref netio_get_buffer()). Use of
							 | 
						||
| 
								 | 
							
								 * this function on an 'ingress' packet will cause an assertion failure.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to the packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_pkt_minimal_metadata_t*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_MINIMAL_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_assert(pkt->__packet.bits.__minimal);
							 | 
						||
| 
								 | 
							
								  return (netio_pkt_minimal_metadata_t*) &pkt->__metadata;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether a packet has 'minimal' metadata.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This function will return nonzero if the packet is an 'egress'
							 | 
						||
| 
								 | 
							
								 * packet (i.e. one on which @ref netio_populate_buffer() or
							 | 
						||
| 
								 | 
							
								 * @ref netio_populate_prepend_buffer() have been called, or one
							 | 
						||
| 
								 | 
							
								 * retrieved by @ref netio_get_buffer()), and zero if the packet
							 | 
						||
| 
								 | 
							
								 * is an 'ingress' packet (i.e. one retrieved by @ref netio_get_packet(),
							 | 
						||
| 
								 | 
							
								 * which has not been converted into an 'egress' packet).
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the packet has minimal metadata.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_IS_MINIMAL(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return pkt->__packet.bits.__minimal;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a handle for a packet's storage.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A handle for the packet's storage.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_pkt_handle_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_HANDLE(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_handle_t h;
							 | 
						||
| 
								 | 
							
								  h.word = pkt->__packet.word;
							 | 
						||
| 
								 | 
							
								  return h;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** A special reserved value indicating the absence of a packet handle.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_PKT_HANDLE_NONE ((netio_pkt_handle_t) { 0 })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Test whether a packet handle is valid.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Applications may wish to use the reserved value NETIO_PKT_HANDLE_NONE
							 | 
						||
| 
								 | 
							
								 * to indicate no packet at all.  This function tests to see if a packet
							 | 
						||
| 
								 | 
							
								 * handle is a real handle, not this special reserved value.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] handle Handle on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return One if the packet handle is valid, else zero.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_HANDLE_IS_VALID(netio_pkt_handle_t handle)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return handle.word != 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the start of the packet's custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] handle Handle on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to start of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_DATA_H(netio_pkt_handle_t handle)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return _NETIO_PKT_HANDLE_BASE(handle) + NETIO_PACKET_PADDING;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet's custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet's custom header, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_HEADER_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								   * Note that we effectively need to extract a quantity from the flags word
							 | 
						||
| 
								 | 
							
								   * which is measured in words, and then turn it into bytes by shifting
							 | 
						||
| 
								 | 
							
								   * it left by 2.  We do this all at once by just shifting right two less
							 | 
						||
| 
								 | 
							
								   * bits, and shifting the mask up two bits.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  return ((mda->__flags >> (_NETIO_PKT_CUSTOM_LEN_SHIFT - 2)) &
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_CUSTOM_LEN_RMASK << 2));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet, starting with the custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (__NETIO_PKT_NOTIF_HEADER(pkt).bits.__transfer_size -
							 | 
						||
| 
								 | 
							
								          NETIO_PACKET_PADDING);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the start of the packet's custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to start of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_DATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_CUSTOM_DATA_H(NETIO_PKT_HANDLE(pkt));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet's L2 (Ethernet plus VLAN or SNAP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet's L2 header, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_HEADER_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								   * Note that we effectively need to extract a quantity from the flags word
							 | 
						||
| 
								 | 
							
								   * which is measured in words, and then turn it into bytes by shifting
							 | 
						||
| 
								 | 
							
								   * it left by 2.  We do this all at once by just shifting right two less
							 | 
						||
| 
								 | 
							
								   * bits, and shifting the mask up two bits.  We then add two bytes.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  return ((mda->__flags >> (_NETIO_PKT_L2_LEN_SHIFT - 2)) &
							 | 
						||
| 
								 | 
							
								          (_NETIO_PKT_L2_LEN_RMASK << 2)) + 2;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet, starting with the L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (NETIO_PKT_CUSTOM_LENGTH_M(mda, pkt) -
							 | 
						||
| 
								 | 
							
								          NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda,pkt));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the start of the packet's L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to start of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_DATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (NETIO_PKT_CUSTOM_DATA_M(mda, pkt) +
							 | 
						||
| 
								 | 
							
								          NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda, pkt));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Retrieve the length of the packet, starting with the L3 (generally,
							 | 
						||
| 
								 | 
							
								 *  the IP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Length of the packet's L3 header and data, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_LENGTH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (NETIO_PKT_L2_LENGTH_M(mda, pkt) -
							 | 
						||
| 
								 | 
							
								          NETIO_PKT_L2_HEADER_LENGTH_M(mda,pkt));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the packet's L3 (generally, the IP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that we guarantee word alignment of the L3 header.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to the packet's L3 header.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_DATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (NETIO_PKT_L2_DATA_M(mda, pkt) +
							 | 
						||
| 
								 | 
							
								          NETIO_PKT_L2_HEADER_LENGTH_M(mda, pkt));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the ordinal of the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Each packet is given an ordinal number when it is delivered by the IPP.
							 | 
						||
| 
								 | 
							
								 * In the medium term, the ordinal is unique and monotonically increasing,
							 | 
						||
| 
								 | 
							
								 * being incremented by 1 for each packet; the ordinal of the first packet
							 | 
						||
| 
								 | 
							
								 * delivered after the IPP starts is zero.  (Since the ordinal is of finite
							 | 
						||
| 
								 | 
							
								 * size, given enough input packets, it will eventually wrap around to zero;
							 | 
						||
| 
								 | 
							
								 * in the long term, therefore, ordinals are not unique.)  The ordinals
							 | 
						||
| 
								 | 
							
								 * handed out by different IPPs are not disjoint, so two packets from
							 | 
						||
| 
								 | 
							
								 * different IPPs may have identical ordinals.  Packets dropped by the
							 | 
						||
| 
								 | 
							
								 * IPP or by the I/O shim are not assigned ordinals.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's per-IPP packet ordinal.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_ORDINAL_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mda->__packet_ordinal;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the per-group ordinal of the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Each packet is given a per-group ordinal number when it is
							 | 
						||
| 
								 | 
							
								 * delivered by the IPP. By default, the group is the packet's VLAN,
							 | 
						||
| 
								 | 
							
								 * although IPP can be recompiled to use different values.  In
							 | 
						||
| 
								 | 
							
								 * the medium term, the ordinal is unique and monotonically
							 | 
						||
| 
								 | 
							
								 * increasing, being incremented by 1 for each packet; the ordinal of
							 | 
						||
| 
								 | 
							
								 * the first packet distributed to a particular group is zero.
							 | 
						||
| 
								 | 
							
								 * (Since the ordinal is of finite size, given enough input packets,
							 | 
						||
| 
								 | 
							
								 * it will eventually wrap around to zero; in the long term,
							 | 
						||
| 
								 | 
							
								 * therefore, ordinals are not unique.)  The ordinals handed out by
							 | 
						||
| 
								 | 
							
								 * different IPPs are not disjoint, so two packets from different IPPs
							 | 
						||
| 
								 | 
							
								 * may have identical ordinals; similarly, packets distributed to
							 | 
						||
| 
								 | 
							
								 * different groups may have identical ordinals.  Packets dropped by
							 | 
						||
| 
								 | 
							
								 * the IPP or by the I/O shim are not assigned ordinals.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's per-IPP, per-group ordinal.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_GROUP_ORDINAL_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mda->__group_ordinal;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the VLAN ID assigned to the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This value is usually contained within the packet header.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This value will be zero if the packet does not have a VLAN tag, or if
							 | 
						||
| 
								 | 
							
								 * this value was not extracted from the packet.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's VLAN ID.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned short
							 | 
						||
| 
								 | 
							
								NETIO_PKT_VLAN_ID_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int vl = (mda->__flags >> _NETIO_PKT_VLAN_SHIFT) & _NETIO_PKT_VLAN_RMASK;
							 | 
						||
| 
								 | 
							
								  unsigned short* pkt_p;
							 | 
						||
| 
								 | 
							
								  int index;
							 | 
						||
| 
								 | 
							
								  unsigned short val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (vl == _NETIO_PKT_VLAN_NONE)
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pkt_p = (unsigned short*) NETIO_PKT_L2_DATA_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  index = (mda->__flags >> _NETIO_PKT_TYPE_SHIFT) & _NETIO_PKT_TYPE_RMASK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  val = pkt_p[(_netio_pkt_info[index] >> _NETIO_PKT_INFO_VLAN_SHIFT) &
							 | 
						||
| 
								 | 
							
								              _NETIO_PKT_INFO_VLAN_RMASK];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __TILECC__
							 | 
						||
| 
								 | 
							
								  return (__insn_bytex(val) >> 16) & 0xFFF;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  return (__builtin_bswap32(val) >> 16) & 0xFFF;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the ethertype of the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This value is usually contained within the packet header.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This value is reliable if @ref NETIO_PKT_ETHERTYPE_RECOGNIZED_M()
							 | 
						||
| 
								 | 
							
								 * returns true, and otherwise, may not be well defined.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's ethertype.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned short
							 | 
						||
| 
								 | 
							
								NETIO_PKT_ETHERTYPE_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  unsigned short* pkt_p = (unsigned short*) NETIO_PKT_L2_DATA_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  int index = (mda->__flags >> _NETIO_PKT_TYPE_SHIFT) & _NETIO_PKT_TYPE_RMASK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  unsigned short val =
							 | 
						||
| 
								 | 
							
								    pkt_p[(_netio_pkt_info[index] >> _NETIO_PKT_INFO_ETYPE_SHIFT) &
							 | 
						||
| 
								 | 
							
								          _NETIO_PKT_INFO_ETYPE_RMASK];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return __builtin_bswap32(val) >> 16;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the flow hash computed on the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For TCP and UDP packets, this hash is calculated by hashing together
							 | 
						||
| 
								 | 
							
								 * the "5-tuple" values, specifically the source IP address, destination
							 | 
						||
| 
								 | 
							
								 * IP address, protocol type, source port and destination port.
							 | 
						||
| 
								 | 
							
								 * The hash value is intended to be helpful for millions of distinct
							 | 
						||
| 
								 | 
							
								 * flows.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For IPv4 or IPv6 packets which are neither TCP nor UDP, the flow hash is
							 | 
						||
| 
								 | 
							
								 * derived by hashing together the source and destination IP addresses.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For MPLS-encapsulated packets, the flow hash is derived by hashing
							 | 
						||
| 
								 | 
							
								 * the first MPLS label.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For all other packets the flow hash is computed from the source
							 | 
						||
| 
								 | 
							
								 * and destination Ethernet addresses.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The hash is symmetric, meaning it produces the same value if the
							 | 
						||
| 
								 | 
							
								 * source and destination are swapped. The only exceptions are
							 | 
						||
| 
								 | 
							
								 * tunneling protocols 0x04 (IP in IP Encapsulation), 0x29 (Simple
							 | 
						||
| 
								 | 
							
								 * Internet Protocol), 0x2F (General Routing Encapsulation) and 0x32
							 | 
						||
| 
								 | 
							
								 * (Encap Security Payload), which use only the destination address
							 | 
						||
| 
								 | 
							
								 * since the source address is not meaningful.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's 32-bit flow hash.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLOW_HASH_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mda->__flow_hash;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the first word of "user data" for the packet.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The contents of the user data words depend on the IPP.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the first
							 | 
						||
| 
								 | 
							
								 * word of user data contains the least significant bits of the 64-bit
							 | 
						||
| 
								 | 
							
								 * arrival cycle count (see @c get_cycle_count_low()).
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * See the <em>System Programmer's Guide</em> for details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's first word of "user data".
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_USER_DATA_0_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mda->__user_data_0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the second word of "user data" for the packet.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The contents of the user data words depend on the IPP.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the second
							 | 
						||
| 
								 | 
							
								 * word of user data contains the most significant bits of the 64-bit
							 | 
						||
| 
								 | 
							
								 * arrival cycle count (see @c get_cycle_count_high()).
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * See the <em>System Programmer's Guide</em> for details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's second word of "user data".
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_USER_DATA_1_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mda->__user_data_1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L4 (TCP/UDP) checksum was calculated.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the L4 checksum was calculated.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L4_CSUM_CALCULATED_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return !(mda->__flags & _NETIO_PKT_NO_L4_CSUM_MASK);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L4 (TCP/UDP) checksum was calculated and found to
							 | 
						||
| 
								 | 
							
								 *  be correct.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the checksum was calculated and is correct.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L4_CSUM_CORRECT_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return !(mda->__flags &
							 | 
						||
| 
								 | 
							
								           (_NETIO_PKT_BAD_L4_CSUM_MASK | _NETIO_PKT_NO_L4_CSUM_MASK));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L3 (IP) checksum was calculated.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the L3 (IP) checksum was calculated.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_CSUM_CALCULATED_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return !(mda->__flags & _NETIO_PKT_NO_L3_CSUM_MASK);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L3 (IP) checksum was calculated and found to be
							 | 
						||
| 
								 | 
							
								 *  correct.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the checksum was calculated and is correct.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_CSUM_CORRECT_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return !(mda->__flags &
							 | 
						||
| 
								 | 
							
								           (_NETIO_PKT_BAD_L3_CSUM_MASK | _NETIO_PKT_NO_L3_CSUM_MASK));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the ethertype was recognized and L3 packet data was
							 | 
						||
| 
								 | 
							
								 *  processed.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the ethertype was recognized and L3 packet data was
							 | 
						||
| 
								 | 
							
								 *   processed.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_ETHERTYPE_RECOGNIZED_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return !(mda->__flags & _NETIO_PKT_TYPE_UNRECOGNIZED_MASK);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Retrieve the status of a packet and any errors that may have occurred
							 | 
						||
| 
								 | 
							
								 * during ingress processing (length mismatches, CRC errors, etc.).
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that packets for which @ref NETIO_PKT_ETHERTYPE_RECOGNIZED()
							 | 
						||
| 
								 | 
							
								 * returns zero are always reported as underlength, as there is no a priori
							 | 
						||
| 
								 | 
							
								 * means to determine their length.  Normally, applications should use
							 | 
						||
| 
								 | 
							
								 * @ref NETIO_PKT_BAD_M() instead of explicitly checking status with this
							 | 
						||
| 
								 | 
							
								 * function.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's status.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_pkt_status_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_STATUS_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (netio_pkt_status_t) __NETIO_PKT_NOTIF_HEADER(pkt).bits.__status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Report whether a packet is bad (i.e., was shorter than expected based on
							 | 
						||
| 
								 | 
							
								 *  its headers, or had a bad CRC).
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that this function does not verify L3 or L4 checksums.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the packet is bad and should be discarded.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_BAD_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return ((NETIO_PKT_STATUS_M(mda, pkt) & 1) &&
							 | 
						||
| 
								 | 
							
								          (NETIO_PKT_ETHERTYPE_RECOGNIZED_M(mda, pkt) ||
							 | 
						||
| 
								 | 
							
								           NETIO_PKT_STATUS_M(mda, pkt) == NETIO_PKT_STATUS_BAD));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet, starting with the L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mmd->l2_length;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet's L2 header, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_HEADER_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd,
							 | 
						||
| 
								 | 
							
								                              netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return mmd->l3_offset - mmd->l2_offset;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet, starting with the L3 (IP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Length of the packet's L3 header and data, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (NETIO_PKT_L2_LENGTH_MM(mmd, pkt) -
							 | 
						||
| 
								 | 
							
								          NETIO_PKT_L2_HEADER_LENGTH_MM(mmd, pkt));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the packet's L3 (generally, the IP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that we guarantee word alignment of the L3 header.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to the packet's L3 header.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_DATA_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return _NETIO_PKT_BASE(pkt) + mmd->l3_offset;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the packet's L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to start of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_DATA_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return _NETIO_PKT_BASE(pkt) + mmd->l2_offset;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Retrieve the status of a packet and any errors that may have occurred
							 | 
						||
| 
								 | 
							
								 * during ingress processing (length mismatches, CRC errors, etc.).
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that packets for which @ref NETIO_PKT_ETHERTYPE_RECOGNIZED()
							 | 
						||
| 
								 | 
							
								 * returns zero are always reported as underlength, as there is no a priori
							 | 
						||
| 
								 | 
							
								 * means to determine their length.  Normally, applications should use
							 | 
						||
| 
								 | 
							
								 * @ref NETIO_PKT_BAD() instead of explicitly checking status with this
							 | 
						||
| 
								 | 
							
								 * function.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's status.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_pkt_status_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_STATUS(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_assert(!pkt->__packet.bits.__minimal);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return (netio_pkt_status_t) __NETIO_PKT_NOTIF_HEADER(pkt).bits.__status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Report whether a packet is bad (i.e., was shorter than expected based on
							 | 
						||
| 
								 | 
							
								 *  its headers, or had a bad CRC).
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that this function does not verify L3 or L4 checksums.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the packet is bad and should be discarded.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_BAD(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_BAD_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet's custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet's custom header, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_HEADER_LENGTH(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet, starting with the custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return  The length of the packet, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_LENGTH(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_CUSTOM_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the packet's custom header.
							 | 
						||
| 
								 | 
							
								 *  A custom header may or may not be present, depending upon the IPP; its
							 | 
						||
| 
								 | 
							
								 *  contents and alignment are also IPP-dependent.  Currently, none of the
							 | 
						||
| 
								 | 
							
								 *  standard IPPs supplied by Tilera produce a custom header.  If present,
							 | 
						||
| 
								 | 
							
								 *  the custom header precedes the L2 header in the packet buffer.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to start of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_CUSTOM_DATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_CUSTOM_DATA_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet's L2 (Ethernet plus VLAN or SNAP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The length of the packet's L2 header, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_HEADER_LENGTH(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L2_HEADER_LENGTH_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L2_HEADER_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the length of the packet, starting with the L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return  The length of the packet, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_LENGTH(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L2_LENGTH_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L2_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the packet's L2 (Ethernet) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to start of the packet.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L2_DATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L2_DATA_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L2_DATA_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Retrieve the length of the packet, starting with the L3 (generally, the IP)
							 | 
						||
| 
								 | 
							
								 * header.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Length of the packet's L3 header and data, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline netio_size_t
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_LENGTH(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L3_LENGTH_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L3_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return a pointer to the packet's L3 (generally, the IP) header.
							 | 
						||
| 
								 | 
							
								 * @ingroup pktfuncs
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that we guarantee word alignment of the L3 header.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return A pointer to the packet's L3 header.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned char*
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_DATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L3_DATA_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_L3_DATA_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the ordinal of the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Each packet is given an ordinal number when it is delivered by the IPP.
							 | 
						||
| 
								 | 
							
								 * In the medium term, the ordinal is unique and monotonically increasing,
							 | 
						||
| 
								 | 
							
								 * being incremented by 1 for each packet; the ordinal of the first packet
							 | 
						||
| 
								 | 
							
								 * delivered after the IPP starts is zero.  (Since the ordinal is of finite
							 | 
						||
| 
								 | 
							
								 * size, given enough input packets, it will eventually wrap around to zero;
							 | 
						||
| 
								 | 
							
								 * in the long term, therefore, ordinals are not unique.)  The ordinals
							 | 
						||
| 
								 | 
							
								 * handed out by different IPPs are not disjoint, so two packets from
							 | 
						||
| 
								 | 
							
								 * different IPPs may have identical ordinals.  Packets dropped by the
							 | 
						||
| 
								 | 
							
								 * IPP or by the I/O shim are not assigned ordinals.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's per-IPP packet ordinal.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_ORDINAL(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_ORDINAL_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the per-group ordinal of the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Each packet is given a per-group ordinal number when it is
							 | 
						||
| 
								 | 
							
								 * delivered by the IPP. By default, the group is the packet's VLAN,
							 | 
						||
| 
								 | 
							
								 * although IPP can be recompiled to use different values.  In
							 | 
						||
| 
								 | 
							
								 * the medium term, the ordinal is unique and monotonically
							 | 
						||
| 
								 | 
							
								 * increasing, being incremented by 1 for each packet; the ordinal of
							 | 
						||
| 
								 | 
							
								 * the first packet distributed to a particular group is zero.
							 | 
						||
| 
								 | 
							
								 * (Since the ordinal is of finite size, given enough input packets,
							 | 
						||
| 
								 | 
							
								 * it will eventually wrap around to zero; in the long term,
							 | 
						||
| 
								 | 
							
								 * therefore, ordinals are not unique.)  The ordinals handed out by
							 | 
						||
| 
								 | 
							
								 * different IPPs are not disjoint, so two packets from different IPPs
							 | 
						||
| 
								 | 
							
								 * may have identical ordinals; similarly, packets distributed to
							 | 
						||
| 
								 | 
							
								 * different groups may have identical ordinals.  Packets dropped by
							 | 
						||
| 
								 | 
							
								 * the IPP or by the I/O shim are not assigned ordinals.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's per-IPP, per-group ordinal.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_GROUP_ORDINAL(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_GROUP_ORDINAL_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the VLAN ID assigned to the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This is usually also contained within the packet header.  If the packet
							 | 
						||
| 
								 | 
							
								 * does not have a VLAN tag, the VLAN ID returned by this function is zero.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's VLAN ID.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned short
							 | 
						||
| 
								 | 
							
								NETIO_PKT_VLAN_ID(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_VLAN_ID_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the ethertype of the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This value is reliable if @ref NETIO_PKT_ETHERTYPE_RECOGNIZED()
							 | 
						||
| 
								 | 
							
								 * returns true, and otherwise, may not be well defined.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's ethertype.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned short
							 | 
						||
| 
								 | 
							
								NETIO_PKT_ETHERTYPE(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_ETHERTYPE_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the flow hash computed on the packet.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For TCP and UDP packets, this hash is calculated by hashing together
							 | 
						||
| 
								 | 
							
								 * the "5-tuple" values, specifically the source IP address, destination
							 | 
						||
| 
								 | 
							
								 * IP address, protocol type, source port and destination port.
							 | 
						||
| 
								 | 
							
								 * The hash value is intended to be helpful for millions of distinct
							 | 
						||
| 
								 | 
							
								 * flows.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For IPv4 or IPv6 packets which are neither TCP nor UDP, the flow hash is
							 | 
						||
| 
								 | 
							
								 * derived by hashing together the source and destination IP addresses.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For MPLS-encapsulated packets, the flow hash is derived by hashing
							 | 
						||
| 
								 | 
							
								 * the first MPLS label.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * For all other packets the flow hash is computed from the source
							 | 
						||
| 
								 | 
							
								 * and destination Ethernet addresses.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The hash is symmetric, meaning it produces the same value if the
							 | 
						||
| 
								 | 
							
								 * source and destination are swapped. The only exceptions are
							 | 
						||
| 
								 | 
							
								 * tunneling protocols 0x04 (IP in IP Encapsulation), 0x29 (Simple
							 | 
						||
| 
								 | 
							
								 * Internet Protocol), 0x2F (General Routing Encapsulation) and 0x32
							 | 
						||
| 
								 | 
							
								 * (Encap Security Payload), which use only the destination address
							 | 
						||
| 
								 | 
							
								 * since the source address is not meaningful.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's 32-bit flow hash.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLOW_HASH(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_FLOW_HASH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the first word of "user data" for the packet.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The contents of the user data words depend on the IPP.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the first
							 | 
						||
| 
								 | 
							
								 * word of user data contains the least significant bits of the 64-bit
							 | 
						||
| 
								 | 
							
								 * arrival cycle count (see @c get_cycle_count_low()).
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * See the <em>System Programmer's Guide</em> for details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's first word of "user data".
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_USER_DATA_0(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_USER_DATA_0_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the second word of "user data" for the packet.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The contents of the user data words depend on the IPP.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * When using the standard ipp1, ipp2, or ipp4 sub-drivers, the second
							 | 
						||
| 
								 | 
							
								 * word of user data contains the most significant bits of the 64-bit
							 | 
						||
| 
								 | 
							
								 * arrival cycle count (see @c get_cycle_count_high()).
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * See the <em>System Programmer's Guide</em> for details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return The packet's second word of "user data".
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_USER_DATA_1(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_USER_DATA_1_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L4 (TCP/UDP) checksum was calculated.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the L4 checksum was calculated.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L4_CSUM_CALCULATED(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_L4_CSUM_CALCULATED_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L4 (TCP/UDP) checksum was calculated and found to
							 | 
						||
| 
								 | 
							
								 *  be correct.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the checksum was calculated and is correct.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L4_CSUM_CORRECT(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_L4_CSUM_CORRECT_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L3 (IP) checksum was calculated.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the L3 (IP) checksum was calculated.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_CSUM_CALCULATED(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_L3_CSUM_CALCULATED_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the L3 (IP) checksum was calculated and found to be
							 | 
						||
| 
								 | 
							
								 *  correct.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the checksum was calculated and is correct.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_L3_CSUM_CORRECT(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_L3_CSUM_CORRECT_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether the Ethertype was recognized and L3 packet data was
							 | 
						||
| 
								 | 
							
								 *  processed.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @return Nonzero if the Ethertype was recognized and L3 packet data was
							 | 
						||
| 
								 | 
							
								 *   processed.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline unsigned int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_ETHERTYPE_RECOGNIZED(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return NETIO_PKT_ETHERTYPE_RECOGNIZED_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set an egress packet's L2 length, using a metadata pointer to speed the
							 | 
						||
| 
								 | 
							
								 * computation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @param[in] len Packet L2 length, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_SET_L2_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt,
							 | 
						||
| 
								 | 
							
								                           int len)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mmd->l2_length = len;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set an egress packet's L2 length.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @param[in] len Packet L2 length, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_SET_L2_LENGTH(netio_pkt_t* pkt, int len)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_SET_L2_LENGTH_MM(mmd, pkt, len);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set an egress packet's L2 header length, using a metadata pointer to
							 | 
						||
| 
								 | 
							
								 *  speed the computation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * It is not normally necessary to call this routine; only the L2 length,
							 | 
						||
| 
								 | 
							
								 * not the header length, is needed to transmit a packet.  It may be useful if
							 | 
						||
| 
								 | 
							
								 * the egress packet will later be processed by code which expects to use
							 | 
						||
| 
								 | 
							
								 * functions like @ref NETIO_PKT_L3_DATA() to get a pointer to the L3 payload.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @param[in] len Packet L2 header length, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_SET_L2_HEADER_LENGTH_MM(netio_pkt_minimal_metadata_t* mmd,
							 | 
						||
| 
								 | 
							
								                                  netio_pkt_t* pkt, int len)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mmd->l3_offset = mmd->l2_offset + len;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set an egress packet's L2 header length.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * It is not normally necessary to call this routine; only the L2 length,
							 | 
						||
| 
								 | 
							
								 * not the header length, is needed to transmit a packet.  It may be useful if
							 | 
						||
| 
								 | 
							
								 * the egress packet will later be processed by code which expects to use
							 | 
						||
| 
								 | 
							
								 * functions like @ref NETIO_PKT_L3_DATA() to get a pointer to the L3 payload.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @param[in] len Packet L2 header length, in bytes.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_SET_L2_HEADER_LENGTH(netio_pkt_t* pkt, int len)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_SET_L2_HEADER_LENGTH_MM(mmd, pkt, len);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set up an egress packet for hardware checksum computation, using a
							 | 
						||
| 
								 | 
							
								 *  metadata pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  NetIO provides the ability to automatically calculate a standard
							 | 
						||
| 
								 | 
							
								 *  16-bit Internet checksum on transmitted packets.  The application
							 | 
						||
| 
								 | 
							
								 *  may specify the point in the packet where the checksum starts, the
							 | 
						||
| 
								 | 
							
								 *  number of bytes to be checksummed, and the two bytes in the packet
							 | 
						||
| 
								 | 
							
								 *  which will be replaced with the completed checksum.  (If the range
							 | 
						||
| 
								 | 
							
								 *  of bytes to be checksummed includes the bytes to be replaced, the
							 | 
						||
| 
								 | 
							
								 *  initial values of those bytes will be included in the checksum.)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  For some protocols, the packet checksum covers data which is not present
							 | 
						||
| 
								 | 
							
								 *  in the packet, or is at least not contiguous to the main data payload.
							 | 
						||
| 
								 | 
							
								 *  For instance, the TCP checksum includes a "pseudo-header" which includes
							 | 
						||
| 
								 | 
							
								 *  the source and destination IP addresses of the packet.  To accommodate
							 | 
						||
| 
								 | 
							
								 *  this, the checksum engine may be "seeded" with an initial value, which
							 | 
						||
| 
								 | 
							
								 *  the application would need to compute based on the specific protocol's
							 | 
						||
| 
								 | 
							
								 *  requirements.  Note that the seed is given in host byte order (little-
							 | 
						||
| 
								 | 
							
								 *  endian), not network byte order (big-endian); code written to compute a
							 | 
						||
| 
								 | 
							
								 *  pseudo-header checksum in network byte order will need to byte-swap it
							 | 
						||
| 
								 | 
							
								 *  before use as the seed.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  Note that the checksum is computed as part of the transmission process,
							 | 
						||
| 
								 | 
							
								 *  so it will not be present in the packet upon completion of this routine.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @param[in] start Offset within L2 packet of the first byte to include in
							 | 
						||
| 
								 | 
							
								 *   the checksum.
							 | 
						||
| 
								 | 
							
								 * @param[in] length Number of bytes to include in the checksum.
							 | 
						||
| 
								 | 
							
								 *   the checksum.
							 | 
						||
| 
								 | 
							
								 * @param[in] location Offset within L2 packet of the first of the two bytes
							 | 
						||
| 
								 | 
							
								 *   to be replaced with the calculated checksum.
							 | 
						||
| 
								 | 
							
								 * @param[in] seed Initial value of the running checksum before any of the
							 | 
						||
| 
								 | 
							
								 *   packet data is added.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_DO_EGRESS_CSUM_MM(netio_pkt_minimal_metadata_t* mmd,
							 | 
						||
| 
								 | 
							
								                            netio_pkt_t* pkt, int start, int length,
							 | 
						||
| 
								 | 
							
								                            int location, uint16_t seed)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mmd->csum_start = start;
							 | 
						||
| 
								 | 
							
								  mmd->csum_length = length;
							 | 
						||
| 
								 | 
							
								  mmd->csum_location = location;
							 | 
						||
| 
								 | 
							
								  mmd->csum_seed = seed;
							 | 
						||
| 
								 | 
							
								  mmd->flags |= _NETIO_PKT_NEED_EDMA_CSUM_MASK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set up an egress packet for hardware checksum computation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  NetIO provides the ability to automatically calculate a standard
							 | 
						||
| 
								 | 
							
								 *  16-bit Internet checksum on transmitted packets.  The application
							 | 
						||
| 
								 | 
							
								 *  may specify the point in the packet where the checksum starts, the
							 | 
						||
| 
								 | 
							
								 *  number of bytes to be checksummed, and the two bytes in the packet
							 | 
						||
| 
								 | 
							
								 *  which will be replaced with the completed checksum.  (If the range
							 | 
						||
| 
								 | 
							
								 *  of bytes to be checksummed includes the bytes to be replaced, the
							 | 
						||
| 
								 | 
							
								 *  initial values of those bytes will be included in the checksum.)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  For some protocols, the packet checksum covers data which is not present
							 | 
						||
| 
								 | 
							
								 *  in the packet, or is at least not contiguous to the main data payload.
							 | 
						||
| 
								 | 
							
								 *  For instance, the TCP checksum includes a "pseudo-header" which includes
							 | 
						||
| 
								 | 
							
								 *  the source and destination IP addresses of the packet.  To accommodate
							 | 
						||
| 
								 | 
							
								 *  this, the checksum engine may be "seeded" with an initial value, which
							 | 
						||
| 
								 | 
							
								 *  the application would need to compute based on the specific protocol's
							 | 
						||
| 
								 | 
							
								 *  requirements.  Note that the seed is given in host byte order (little-
							 | 
						||
| 
								 | 
							
								 *  endian), not network byte order (big-endian); code written to compute a
							 | 
						||
| 
								 | 
							
								 *  pseudo-header checksum in network byte order will need to byte-swap it
							 | 
						||
| 
								 | 
							
								 *  before use as the seed.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  Note that the checksum is computed as part of the transmission process,
							 | 
						||
| 
								 | 
							
								 *  so it will not be present in the packet upon completion of this routine.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 * @param[in] start Offset within L2 packet of the first byte to include in
							 | 
						||
| 
								 | 
							
								 *   the checksum.
							 | 
						||
| 
								 | 
							
								 * @param[in] length Number of bytes to include in the checksum.
							 | 
						||
| 
								 | 
							
								 *   the checksum.
							 | 
						||
| 
								 | 
							
								 * @param[in] location Offset within L2 packet of the first of the two bytes
							 | 
						||
| 
								 | 
							
								 *   to be replaced with the calculated checksum.
							 | 
						||
| 
								 | 
							
								 * @param[in] seed Initial value of the running checksum before any of the
							 | 
						||
| 
								 | 
							
								 *   packet data is added.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_DO_EGRESS_CSUM(netio_pkt_t* pkt, int start, int length,
							 | 
						||
| 
								 | 
							
								                         int location, uint16_t seed)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  NETIO_PKT_DO_EGRESS_CSUM_MM(mmd, pkt, start, length, location, seed);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the number of bytes which could be prepended to a packet, using a
							 | 
						||
| 
								 | 
							
								 *  metadata pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 *  See @ref netio_populate_prepend_buffer() to get a full description of
							 | 
						||
| 
								 | 
							
								 *  prepending.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] mda Pointer to packet's standard metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_PREPEND_AVAIL_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (pkt->__packet.bits.__offset << 6) +
							 | 
						||
| 
								 | 
							
								         NETIO_PKT_CUSTOM_HEADER_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the number of bytes which could be prepended to a packet, using a
							 | 
						||
| 
								 | 
							
								 *  metadata pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 *  See @ref netio_populate_prepend_buffer() to get a full description of
							 | 
						||
| 
								 | 
							
								 *  prepending.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in,out] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_PREPEND_AVAIL_MM(netio_pkt_minimal_metadata_t* mmd, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (pkt->__packet.bits.__offset << 6) + mmd->l2_offset;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return the number of bytes which could be prepended to a packet.
							 | 
						||
| 
								 | 
							
								 *  See @ref netio_populate_prepend_buffer() to get a full description of
							 | 
						||
| 
								 | 
							
								 *  prepending.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline int
							 | 
						||
| 
								 | 
							
								NETIO_PKT_PREPEND_AVAIL(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_minimal_metadata_t* mmd = NETIO_PKT_MINIMAL_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_PREPEND_AVAIL_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    netio_pkt_metadata_t* mda = NETIO_PKT_METADATA(pkt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return NETIO_PKT_PREPEND_AVAIL_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush a packet's minimal metadata from the cache, using a metadata pointer
							 | 
						||
| 
								 | 
							
								 *  to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_MINIMAL_METADATA_MM(netio_pkt_minimal_metadata_t* mmd,
							 | 
						||
| 
								 | 
							
								                                    netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Invalidate a packet's minimal metadata from the cache, using a metadata
							 | 
						||
| 
								 | 
							
								 *  pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_INV_MINIMAL_METADATA_MM(netio_pkt_minimal_metadata_t* mmd,
							 | 
						||
| 
								 | 
							
								                                  netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush and then invalidate a packet's minimal metadata from the cache,
							 | 
						||
| 
								 | 
							
								 *  using a metadata pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mmd Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_INV_MINIMAL_METADATA_MM(netio_pkt_minimal_metadata_t* mmd,
							 | 
						||
| 
								 | 
							
								                                        netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush a packet's metadata from the cache, using a metadata pointer
							 | 
						||
| 
								 | 
							
								 *  to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's minimal metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_METADATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Invalidate a packet's metadata from the cache, using a metadata
							 | 
						||
| 
								 | 
							
								 *  pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_INV_METADATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush and then invalidate a packet's metadata from the cache,
							 | 
						||
| 
								 | 
							
								 *  using a metadata pointer to speed the operation.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] mda Pointer to packet's metadata.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_INV_METADATA_M(netio_pkt_metadata_t* mda, netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush a packet's minimal metadata from the cache.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_MINIMAL_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Invalidate a packet's minimal metadata from the cache.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_INV_MINIMAL_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush and then invalidate a packet's minimal metadata from the cache.
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_INV_MINIMAL_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush a packet's metadata from the cache.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Invalidate a packet's metadata from the cache.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_INV_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Flush and then invalidate a packet's metadata from the cache.
							 | 
						||
| 
								 | 
							
								 * @ingroup ingress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet on which to operate.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								NETIO_PKT_FLUSH_INV_METADATA(netio_pkt_t* pkt)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Number of NUMA nodes we can distribute buffers to.
							 | 
						||
| 
								 | 
							
								 * @ingroup setup */
							 | 
						||
| 
								 | 
							
								#define NETIO_NUM_NODE_WEIGHTS  16
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief An object for specifying the characteristics of NetIO communication
							 | 
						||
| 
								 | 
							
								 * endpoint.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup setup
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The @ref netio_input_register() function uses this structure to define
							 | 
						||
| 
								 | 
							
								 * how an application tile will communicate with an IPP.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Future updates to NetIO may add new members to this structure,
							 | 
						||
| 
								 | 
							
								 * which can affect the success of the registration operation.  Thus,
							 | 
						||
| 
								 | 
							
								 * if dynamically initializing the structure, applications are urged to
							 | 
						||
| 
								 | 
							
								 * zero it out first, for example:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @code
							 | 
						||
| 
								 | 
							
								 * netio_input_config_t config;
							 | 
						||
| 
								 | 
							
								 * memset(&config, 0, sizeof (config));
							 | 
						||
| 
								 | 
							
								 * config.flags = NETIO_RECV | NETIO_XMIT_CSUM | NETIO_TAG_NONE;
							 | 
						||
| 
								 | 
							
								 * config.num_receive_packets = NETIO_MAX_RECEIVE_PKTS;
							 | 
						||
| 
								 | 
							
								 * config.queue_id = 0;
							 | 
						||
| 
								 | 
							
								 *     .
							 | 
						||
| 
								 | 
							
								 *     .
							 | 
						||
| 
								 | 
							
								 *     .
							 | 
						||
| 
								 | 
							
								 * @endcode
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * since that guarantees that any unused structure members, including
							 | 
						||
| 
								 | 
							
								 * members which did not exist when the application was first developed,
							 | 
						||
| 
								 | 
							
								 * will not have unexpected values.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * If statically initializing the structure, we strongly recommend use of
							 | 
						||
| 
								 | 
							
								 * C99-style named initializers, for example:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @code
							 | 
						||
| 
								 | 
							
								 * netio_input_config_t config = {
							 | 
						||
| 
								 | 
							
								 *    .flags = NETIO_RECV | NETIO_XMIT_CSUM | NETIO_TAG_NONE,
							 | 
						||
| 
								 | 
							
								 *    .num_receive_packets = NETIO_MAX_RECEIVE_PKTS,
							 | 
						||
| 
								 | 
							
								 *    .queue_id = 0,
							 | 
						||
| 
								 | 
							
								 * },
							 | 
						||
| 
								 | 
							
								 * @endcode
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * instead of the old-style structure initialization:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @code
							 | 
						||
| 
								 | 
							
								 * // Bad example! Currently equivalent to the above, but don't do this.
							 | 
						||
| 
								 | 
							
								 * netio_input_config_t config = {
							 | 
						||
| 
								 | 
							
								 *    NETIO_RECV | NETIO_XMIT_CSUM | NETIO_TAG_NONE, NETIO_MAX_RECEIVE_PKTS, 0
							 | 
						||
| 
								 | 
							
								 * },
							 | 
						||
| 
								 | 
							
								 * @endcode
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * since the C99 style requires no changes to the code if elements of the
							 | 
						||
| 
								 | 
							
								 * config structure are rearranged.  (It also makes the initialization much
							 | 
						||
| 
								 | 
							
								 * easier to understand.)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Except for items which address a particular tile's transmit or receive
							 | 
						||
| 
								 | 
							
								 * characteristics, such as the ::NETIO_RECV flag, applications are advised
							 | 
						||
| 
								 | 
							
								 * to specify the same set of configuration data on all registrations.
							 | 
						||
| 
								 | 
							
								 * This prevents differing results if multiple tiles happen to do their
							 | 
						||
| 
								 | 
							
								 * registration operations in a different order on different invocations of
							 | 
						||
| 
								 | 
							
								 * the application.  This is particularly important for things like link
							 | 
						||
| 
								 | 
							
								 * management flags, and buffer size and homing specifications.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Unless the ::NETIO_FIXED_BUFFER_VA flag is specified in flags, the NetIO
							 | 
						||
| 
								 | 
							
								 * buffer pool is automatically created and mapped into the application's
							 | 
						||
| 
								 | 
							
								 * virtual address space at an address chosen by the operating system,
							 | 
						||
| 
								 | 
							
								 * using the common memory (cmem) facility in the Tilera Multicore
							 | 
						||
| 
								 | 
							
								 * Components library.  The cmem facility allows multiple processes to gain
							 | 
						||
| 
								 | 
							
								 * access to shared memory which is mapped into each process at an
							 | 
						||
| 
								 | 
							
								 * identical virtual address.  In order for this to work, the processes
							 | 
						||
| 
								 | 
							
								 * must have a common ancestor, which must create the common memory using
							 | 
						||
| 
								 | 
							
								 * tmc_cmem_init().
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * In programs using the iLib process creation API, or in programs which use
							 | 
						||
| 
								 | 
							
								 * only one process (which include programs using the pthreads library),
							 | 
						||
| 
								 | 
							
								 * tmc_cmem_init() is called automatically.  All other applications
							 | 
						||
| 
								 | 
							
								 * must call it explicitly, before any child processes which might call
							 | 
						||
| 
								 | 
							
								 * netio_input_register() are created.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /** Registration characteristics.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      This value determines several characteristics of the registration;
							 | 
						||
| 
								 | 
							
								      flags for different types of behavior are ORed together to make the
							 | 
						||
| 
								 | 
							
								      final flag value.  Generally applications should specify exactly
							 | 
						||
| 
								 | 
							
								      one flag from each of the following categories:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - Whether the application will be receiving packets on this queue
							 | 
						||
| 
								 | 
							
								        (::NETIO_RECV or ::NETIO_NO_RECV).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - Whether the application will be transmitting packets on this queue,
							 | 
						||
| 
								 | 
							
								        and if so, whether it will request egress checksum calculation
							 | 
						||
| 
								 | 
							
								        (::NETIO_XMIT, ::NETIO_XMIT_CSUM, or ::NETIO_NO_XMIT).  It is
							 | 
						||
| 
								 | 
							
								        legal to call netio_get_buffer() without one of the XMIT flags,
							 | 
						||
| 
								 | 
							
								        as long as ::NETIO_RECV is specified; in this case, the retrieved
							 | 
						||
| 
								 | 
							
								        buffers must be passed to another tile for transmission.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - Whether the application expects any vendor-specific tags in
							 | 
						||
| 
								 | 
							
								        its packets' L2 headers (::NETIO_TAG_NONE, ::NETIO_TAG_BRCM,
							 | 
						||
| 
								 | 
							
								        or ::NETIO_TAG_MRVL).  This must match the configuration of the
							 | 
						||
| 
								 | 
							
								        target IPP.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      To accommodate applications written to previous versions of the NetIO
							 | 
						||
| 
								 | 
							
								      interface, none of the flags above are currently required; if omitted,
							 | 
						||
| 
								 | 
							
								      NetIO behaves more or less as if ::NETIO_RECV | ::NETIO_XMIT_CSUM |
							 | 
						||
| 
								 | 
							
								      ::NETIO_TAG_NONE were used.  However, explicit specification of
							 | 
						||
| 
								 | 
							
								      the relevant flags allows NetIO to do a better job of resource
							 | 
						||
| 
								 | 
							
								      allocation, allows earlier detection of certain configuration errors,
							 | 
						||
| 
								 | 
							
								      and may enable advanced features or higher performance in the future,
							 | 
						||
| 
								 | 
							
								      so their use is strongly recommended.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Note that specifying ::NETIO_NO_RECV along with ::NETIO_NO_XMIT
							 | 
						||
| 
								 | 
							
								      is a special case, intended primarily for use by programs which
							 | 
						||
| 
								 | 
							
								      retrieve network statistics or do link management operations.
							 | 
						||
| 
								 | 
							
								      When these flags are both specified, the resulting queue may not
							 | 
						||
| 
								 | 
							
								      be used with NetIO routines other than netio_get(), netio_set(),
							 | 
						||
| 
								 | 
							
								      and netio_input_unregister().  See @ref link for more information
							 | 
						||
| 
								 | 
							
								      on link management.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Other flags are optional; their use is described below.
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								  int flags;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Interface name.  This is a string which identifies the specific
							 | 
						||
| 
								 | 
							
								      Ethernet controller hardware to be used.  The format of the string
							 | 
						||
| 
								 | 
							
								      is a device type and a device index, separated by a slash; so,
							 | 
						||
| 
								 | 
							
								      the first 10 Gigabit Ethernet controller is named "xgbe/0", while
							 | 
						||
| 
								 | 
							
								      the second 10/100/1000 Megabit Ethernet controller is named "gbe/1".
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  const char* interface;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Receive packet queue size.  This specifies the maximum number
							 | 
						||
| 
								 | 
							
								      of ingress packets that can be received on this queue without
							 | 
						||
| 
								 | 
							
								      being retrieved by @ref netio_get_packet().  If the IPP's distribution
							 | 
						||
| 
								 | 
							
								      algorithm calls for a packet to be sent to this queue, and this
							 | 
						||
| 
								 | 
							
								      number of packets are already pending there, the new packet
							 | 
						||
| 
								 | 
							
								      will either be discarded, or sent to another tile registered
							 | 
						||
| 
								 | 
							
								      for the same queue_id (see @ref drops).  This value must
							 | 
						||
| 
								 | 
							
								      be at least ::NETIO_MIN_RECEIVE_PKTS, can always be at least
							 | 
						||
| 
								 | 
							
								      ::NETIO_MAX_RECEIVE_PKTS, and may be larger than that on certain
							 | 
						||
| 
								 | 
							
								      interfaces.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_receive_packets;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** The queue ID being requested.  Legal values for this range from 0
							 | 
						||
| 
								 | 
							
								      to ::NETIO_MAX_QUEUE_ID, inclusive.  ::NETIO_MAX_QUEUE_ID is always
							 | 
						||
| 
								 | 
							
								      greater than or equal to the number of tiles; this allows one queue
							 | 
						||
| 
								 | 
							
								      for each tile, plus at least one additional queue.  Some applications
							 | 
						||
| 
								 | 
							
								      may wish to use the additional queue as a destination for unwanted
							 | 
						||
| 
								 | 
							
								      packets, since packets delivered to queues for which no tiles have
							 | 
						||
| 
								 | 
							
								      registered are discarded.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  unsigned int queue_id;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Maximum number of small send buffers to be held in the local empty
							 | 
						||
| 
								 | 
							
								      buffer cache.  This specifies the size of the area which holds
							 | 
						||
| 
								 | 
							
								      empty small egress buffers requested from the IPP but not yet
							 | 
						||
| 
								 | 
							
								      retrieved via @ref netio_get_buffer().  This value must be greater
							 | 
						||
| 
								 | 
							
								      than zero if the application will ever use @ref netio_get_buffer()
							 | 
						||
| 
								 | 
							
								      to allocate empty small egress buffers; it may be no larger than
							 | 
						||
| 
								 | 
							
								      ::NETIO_MAX_SEND_BUFFERS.  See @ref epp for more details on empty
							 | 
						||
| 
								 | 
							
								      buffer caching.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_send_buffers_small_total;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of small send buffers to be preallocated at registration.
							 | 
						||
| 
								 | 
							
								      If this value is nonzero, the specified number of empty small egress
							 | 
						||
| 
								 | 
							
								      buffers will be requested from the IPP during the netio_input_register
							 | 
						||
| 
								 | 
							
								      operation; this may speed the execution of @ref netio_get_buffer().
							 | 
						||
| 
								 | 
							
								      This may be no larger than @ref num_send_buffers_small_total.  See @ref
							 | 
						||
| 
								 | 
							
								      epp for more details on empty buffer caching.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_send_buffers_small_prealloc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Maximum number of large send buffers to be held in the local empty
							 | 
						||
| 
								 | 
							
								      buffer cache.  This specifies the size of the area which holds empty
							 | 
						||
| 
								 | 
							
								      large egress buffers requested from the IPP but not yet retrieved via
							 | 
						||
| 
								 | 
							
								      @ref netio_get_buffer().  This value must be greater than zero if the
							 | 
						||
| 
								 | 
							
								      application will ever use @ref netio_get_buffer() to allocate empty
							 | 
						||
| 
								 | 
							
								      large egress buffers; it may be no larger than ::NETIO_MAX_SEND_BUFFERS.
							 | 
						||
| 
								 | 
							
								      See @ref epp for more details on empty buffer caching.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_send_buffers_large_total;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of large send buffers to be preallocated at registration.
							 | 
						||
| 
								 | 
							
								      If this value is nonzero, the specified number of empty large egress
							 | 
						||
| 
								 | 
							
								      buffers will be requested from the IPP during the netio_input_register
							 | 
						||
| 
								 | 
							
								      operation; this may speed the execution of @ref netio_get_buffer().
							 | 
						||
| 
								 | 
							
								      This may be no larger than @ref num_send_buffers_large_total.  See @ref
							 | 
						||
| 
								 | 
							
								      epp for more details on empty buffer caching.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_send_buffers_large_prealloc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Maximum number of jumbo send buffers to be held in the local empty
							 | 
						||
| 
								 | 
							
								      buffer cache.  This specifies the size of the area which holds empty
							 | 
						||
| 
								 | 
							
								      jumbo egress buffers requested from the IPP but not yet retrieved via
							 | 
						||
| 
								 | 
							
								      @ref netio_get_buffer().  This value must be greater than zero if the
							 | 
						||
| 
								 | 
							
								      application will ever use @ref netio_get_buffer() to allocate empty
							 | 
						||
| 
								 | 
							
								      jumbo egress buffers; it may be no larger than ::NETIO_MAX_SEND_BUFFERS.
							 | 
						||
| 
								 | 
							
								      See @ref epp for more details on empty buffer caching.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_send_buffers_jumbo_total;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of jumbo send buffers to be preallocated at registration.
							 | 
						||
| 
								 | 
							
								      If this value is nonzero, the specified number of empty jumbo egress
							 | 
						||
| 
								 | 
							
								      buffers will be requested from the IPP during the netio_input_register
							 | 
						||
| 
								 | 
							
								      operation; this may speed the execution of @ref netio_get_buffer().
							 | 
						||
| 
								 | 
							
								      This may be no larger than @ref num_send_buffers_jumbo_total.  See @ref
							 | 
						||
| 
								 | 
							
								      epp for more details on empty buffer caching.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_send_buffers_jumbo_prealloc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Total packet buffer size.  This determines the total size, in bytes,
							 | 
						||
| 
								 | 
							
								      of the NetIO buffer pool.  Note that the maximum number of available
							 | 
						||
| 
								 | 
							
								      buffers of each size is determined during hypervisor configuration
							 | 
						||
| 
								 | 
							
								      (see the <em>System Programmer's Guide</em> for details); this just
							 | 
						||
| 
								 | 
							
								      influences how much host memory is allocated for those buffers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      The buffer pool is allocated from common memory, which will be
							 | 
						||
| 
								 | 
							
								      automatically initialized if needed.  If your buffer pool is larger
							 | 
						||
| 
								 | 
							
								      than 240 MB, you might need to explicitly call @c tmc_cmem_init(),
							 | 
						||
| 
								 | 
							
								      as described in the Application Libraries Reference Manual (UG227).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Packet buffers are currently allocated in chunks of 16 MB; this
							 | 
						||
| 
								 | 
							
								      value will be rounded up to the next larger multiple of 16 MB.
							 | 
						||
| 
								 | 
							
								      If this value is zero, a default of 32 MB will be used; this was
							 | 
						||
| 
								 | 
							
								      the value used by previous versions of NetIO.  Note that taking this
							 | 
						||
| 
								 | 
							
								      default also affects the placement of buffers on Linux NUMA nodes.
							 | 
						||
| 
								 | 
							
								      See @ref buffer_node_weights for an explanation of buffer placement.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      In order to successfully allocate packet buffers, Linux must have
							 | 
						||
| 
								 | 
							
								      available huge pages on the relevant Linux NUMA nodes.  See the
							 | 
						||
| 
								 | 
							
								      <em>System Programmer's Guide</em> for information on configuring
							 | 
						||
| 
								 | 
							
								      huge page support in Linux.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  uint64_t total_buffer_size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Buffer placement weighting factors.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      This array specifies the relative amount of buffering to place
							 | 
						||
| 
								 | 
							
								      on each of the available Linux NUMA nodes.  This array is
							 | 
						||
| 
								 | 
							
								      indexed by the NUMA node, and the values in the array are
							 | 
						||
| 
								 | 
							
								      proportional to the amount of buffer space to allocate on that
							 | 
						||
| 
								 | 
							
								      node.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      If memory striping is enabled in the Hypervisor, then there is
							 | 
						||
| 
								 | 
							
								      only one logical NUMA node (node 0). In that case, NetIO will by
							 | 
						||
| 
								 | 
							
								      default ignore the suggested buffer node weights, and buffers
							 | 
						||
| 
								 | 
							
								      will be striped across the physical memory controllers. See
							 | 
						||
| 
								 | 
							
								      UG209 System Programmer's Guide for a description of the
							 | 
						||
| 
								 | 
							
								      hypervisor option that controls memory striping.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      If memory striping is disabled, then there are up to four NUMA
							 | 
						||
| 
								 | 
							
								      nodes, corresponding to the four DDRAM controllers in the TILE
							 | 
						||
| 
								 | 
							
								      processor architecture.  See UG100 Tile Processor Architecture
							 | 
						||
| 
								 | 
							
								      Overview for a diagram showing the location of each of the DDRAM
							 | 
						||
| 
								 | 
							
								      controllers relative to the tile array.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      For instance, if memory striping is disabled, the following
							 | 
						||
| 
								 | 
							
								      configuration strucure:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      @code
							 | 
						||
| 
								 | 
							
								      netio_input_config_t config = {
							 | 
						||
| 
								 | 
							
								            .
							 | 
						||
| 
								 | 
							
								            .
							 | 
						||
| 
								 | 
							
								            .
							 | 
						||
| 
								 | 
							
								        .total_buffer_size = 4 * 16 * 1024 * 1024;
							 | 
						||
| 
								 | 
							
								        .buffer_node_weights = { 1, 0, 1, 0 },
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      @endcode
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      would result in 32 MB of buffers being placed on controller 0, and
							 | 
						||
| 
								 | 
							
								      32 MB on controller 2.  (Since buffers are allocated in units of
							 | 
						||
| 
								 | 
							
								      16 MB, some sets of weights will not be able to be matched exactly.)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      For the weights to be effective, @ref total_buffer_size must be
							 | 
						||
| 
								 | 
							
								      nonzero.  If @ref total_buffer_size is zero, causing the default
							 | 
						||
| 
								 | 
							
								      32 MB of buffer space to be used, then any specified weights will
							 | 
						||
| 
								 | 
							
								      be ignored, and buffers will positioned as they were in previous
							 | 
						||
| 
								 | 
							
								      versions of NetIO:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - For xgbe/0 and gbe/0, 16 MB of buffers will be placed on controller 1,
							 | 
						||
| 
								 | 
							
								        and the other 16 MB will be placed on controller 2.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - For xgbe/1 and gbe/1, 16 MB of buffers will be placed on controller 2,
							 | 
						||
| 
								 | 
							
								        and the other 16 MB will be placed on controller 3.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      If @ref total_buffer_size is nonzero, but all weights are zero,
							 | 
						||
| 
								 | 
							
								      then all buffer space will be allocated on Linux NUMA node zero.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      By default, the specified buffer placement is treated as a hint;
							 | 
						||
| 
								 | 
							
								      if sufficient free memory is not available on the specified
							 | 
						||
| 
								 | 
							
								      controllers, the buffers will be allocated elsewhere.  However,
							 | 
						||
| 
								 | 
							
								      if the ::NETIO_STRICT_HOMING flag is specified in @ref flags, then a
							 | 
						||
| 
								 | 
							
								      failure to allocate buffer space exactly as requested will cause the
							 | 
						||
| 
								 | 
							
								      registration operation to fail with an error of ::NETIO_CANNOT_HOME.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Note that maximal network performance cannot be achieved with
							 | 
						||
| 
								 | 
							
								      only one memory controller.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  uint8_t buffer_node_weights[NETIO_NUM_NODE_WEIGHTS];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Fixed virtual address for packet buffers.  Only valid when
							 | 
						||
| 
								 | 
							
								      ::NETIO_FIXED_BUFFER_VA is specified in @ref flags; see the
							 | 
						||
| 
								 | 
							
								      description of that flag for details.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  void* fixed_buffer_va;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								      Maximum number of outstanding send packet requests.  This value is
							 | 
						||
| 
								 | 
							
								      only relevant when an EPP is in use; it determines the number of
							 | 
						||
| 
								 | 
							
								      slots in the EPP's outgoing packet queue which this tile is allowed
							 | 
						||
| 
								 | 
							
								      to consume, and thus the number of packets which may be sent before
							 | 
						||
| 
								 | 
							
								      the sending tile must wait for an acknowledgment from the EPP.
							 | 
						||
| 
								 | 
							
								      Modifying this value is generally only helpful when using @ref
							 | 
						||
| 
								 | 
							
								      netio_send_packet_vector(), where it can help improve performance by
							 | 
						||
| 
								 | 
							
								      allowing a single vector send operation to process more packets.
							 | 
						||
| 
								 | 
							
								      Typically it is not specified, and the default, which divides the
							 | 
						||
| 
								 | 
							
								      outgoing packet slots evenly between all tiles on the chip, is used.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      If a registration asks for more outgoing packet queue slots than are
							 | 
						||
| 
								 | 
							
								      available, ::NETIO_TOOMANY_XMIT will be returned.  The total number
							 | 
						||
| 
								 | 
							
								      of packet queue slots which are available for all tiles for each EPP
							 | 
						||
| 
								 | 
							
								      is subject to change, but is currently ::NETIO_TOTAL_SENDS_OUTSTANDING.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      This value is ignored if ::NETIO_XMIT is not specified in flags.
							 | 
						||
| 
								 | 
							
								      If you want to specify a large value here for a specific tile, you are
							 | 
						||
| 
								 | 
							
								      advised to specify NETIO_NO_XMIT on other, non-transmitting tiles so
							 | 
						||
| 
								 | 
							
								      that they do not consume a default number of packet slots.  Any tile
							 | 
						||
| 
								 | 
							
								      transmitting is required to have at least ::NETIO_MIN_SENDS_OUTSTANDING
							 | 
						||
| 
								 | 
							
								      slots allocated to it; values less than that will be silently
							 | 
						||
| 
								 | 
							
								      increased by the NetIO library.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  int num_sends_outstanding;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_input_config_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Registration flags; used in the @ref netio_input_config_t structure.
							 | 
						||
| 
								 | 
							
								 * @addtogroup setup
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								/** @{ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Fail a registration request if we can't put packet buffers
							 | 
						||
| 
								 | 
							
								    on the specified memory controllers. */
							 | 
						||
| 
								 | 
							
								#define NETIO_STRICT_HOMING   0x00000002
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This application expects no tags on its L2 headers. */
							 | 
						||
| 
								 | 
							
								#define NETIO_TAG_NONE        0x00000004
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This application expects Marvell extended tags on its L2 headers. */
							 | 
						||
| 
								 | 
							
								#define NETIO_TAG_MRVL        0x00000008
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This application expects Broadcom tags on its L2 headers. */
							 | 
						||
| 
								 | 
							
								#define NETIO_TAG_BRCM        0x00000010
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration may call routines which receive packets. */
							 | 
						||
| 
								 | 
							
								#define NETIO_RECV            0x00000020
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration may not call routines which receive packets. */
							 | 
						||
| 
								 | 
							
								#define NETIO_NO_RECV         0x00000040
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration may call routines which transmit packets. */
							 | 
						||
| 
								 | 
							
								#define NETIO_XMIT            0x00000080
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration may call routines which transmit packets with
							 | 
						||
| 
								 | 
							
								    checksum acceleration. */
							 | 
						||
| 
								 | 
							
								#define NETIO_XMIT_CSUM       0x00000100
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration may not call routines which transmit packets. */
							 | 
						||
| 
								 | 
							
								#define NETIO_NO_XMIT         0x00000200
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration wants NetIO buffers mapped at an application-specified
							 | 
						||
| 
								 | 
							
								    virtual address.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    NetIO buffers are by default created by the TMC common memory facility,
							 | 
						||
| 
								 | 
							
								    which must be configured by a common ancestor of all processes sharing
							 | 
						||
| 
								 | 
							
								    a network interface.  When this flag is specified, NetIO buffers are
							 | 
						||
| 
								 | 
							
								    instead mapped at an address chosen by the application (and specified
							 | 
						||
| 
								 | 
							
								    in @ref netio_input_config_t::fixed_buffer_va).  This allows multiple
							 | 
						||
| 
								 | 
							
								    unrelated but cooperating processes to share a NetIO interface.
							 | 
						||
| 
								 | 
							
								    All processes sharing the same interface must specify this flag,
							 | 
						||
| 
								 | 
							
								    and all must specify the same fixed virtual address.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @ref netio_input_config_t::fixed_buffer_va must be a
							 | 
						||
| 
								 | 
							
								    multiple of 16 MB, and the packet buffers will occupy @ref
							 | 
						||
| 
								 | 
							
								    netio_input_config_t::total_buffer_size bytes of virtual address
							 | 
						||
| 
								 | 
							
								    space, beginning at that address.  If any of those virtual addresses
							 | 
						||
| 
								 | 
							
								    are currently occupied by other memory objects, like application or
							 | 
						||
| 
								 | 
							
								    shared library code or data, @ref netio_input_register() will return
							 | 
						||
| 
								 | 
							
								    ::NETIO_FAULT.  While it is impossible to provide a fixed_buffer_va
							 | 
						||
| 
								 | 
							
								    which will work for all applications, a good first guess might be to
							 | 
						||
| 
								 | 
							
								    use 0xb0000000 minus @ref netio_input_config_t::total_buffer_size.
							 | 
						||
| 
								 | 
							
								    If that fails, it might be helpful to consult the running application's
							 | 
						||
| 
								 | 
							
								    virtual address description file (/proc/<em>pid</em>/maps) to see
							 | 
						||
| 
								 | 
							
								    which regions of virtual address space are available.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_FIXED_BUFFER_VA 0x00000400
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration call will not complete unless the network link
							 | 
						||
| 
								 | 
							
								    is up.  The process will wait several seconds for this to happen (the
							 | 
						||
| 
								 | 
							
								    precise interval is link-dependent), but if the link does not come up,
							 | 
						||
| 
								 | 
							
								    ::NETIO_LINK_DOWN will be returned.  This flag is the default if
							 | 
						||
| 
								 | 
							
								    ::NETIO_NOREQUIRE_LINK_UP is not specified.  Note that this flag by
							 | 
						||
| 
								 | 
							
								    itself does not request that the link be brought up; that can be done
							 | 
						||
| 
								 | 
							
								    with the ::NETIO_AUTO_LINK_UPDN or ::NETIO_AUTO_LINK_UP flags (the
							 | 
						||
| 
								 | 
							
								    latter is the default if no NETIO_AUTO_LINK_xxx flags are specified),
							 | 
						||
| 
								 | 
							
								    or by explicitly setting the link's desired state via netio_set().
							 | 
						||
| 
								 | 
							
								    If the link is not brought up by one of those methods, and this flag
							 | 
						||
| 
								 | 
							
								    is specified, the registration operation will return ::NETIO_LINK_DOWN.
							 | 
						||
| 
								 | 
							
								    This flag is ignored if it is specified along with ::NETIO_NO_XMIT and
							 | 
						||
| 
								 | 
							
								    ::NETIO_NO_RECV.  See @ref link for more information on link
							 | 
						||
| 
								 | 
							
								    management.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_REQUIRE_LINK_UP    0x00000800
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** This registration call will complete even if the network link is not up.
							 | 
						||
| 
								 | 
							
								    Whenever the link is not up, packets will not be sent or received:
							 | 
						||
| 
								 | 
							
								    netio_get_packet() will return ::NETIO_NOPKT once all queued packets
							 | 
						||
| 
								 | 
							
								    have been drained, and netio_send_packet() and similar routines will
							 | 
						||
| 
								 | 
							
								    return NETIO_QUEUE_FULL once the outgoing packet queue in the EPP
							 | 
						||
| 
								 | 
							
								    or the I/O shim is full.  See @ref link for more information on link
							 | 
						||
| 
								 | 
							
								    management.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_NOREQUIRE_LINK_UP  0x00001000
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * These are part of the implementation of the NETIO_AUTO_LINK_xxx flags,
							 | 
						||
| 
								 | 
							
								 * but should not be used directly by applications, and are thus not
							 | 
						||
| 
								 | 
							
								 * documented.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define _NETIO_AUTO_UP        0x00002000
							 | 
						||
| 
								 | 
							
								#define _NETIO_AUTO_DN        0x00004000
							 | 
						||
| 
								 | 
							
								#define _NETIO_AUTO_PRESENT   0x00008000
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set the desired state of the link to up, allowing any speeds which are
							 | 
						||
| 
								 | 
							
								    supported by the link hardware, as part of this registration operation.
							 | 
						||
| 
								 | 
							
								    Do not take down the link automatically.  This is the default if
							 | 
						||
| 
								 | 
							
								    no other NETIO_AUTO_LINK_xxx flags are specified.  This flag is ignored
							 | 
						||
| 
								 | 
							
								    if it is specified along with ::NETIO_NO_XMIT and ::NETIO_NO_RECV.
							 | 
						||
| 
								 | 
							
								    See @ref link for more information on link management.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_AUTO_LINK_UP     (_NETIO_AUTO_PRESENT | _NETIO_AUTO_UP)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set the desired state of the link to up, allowing any speeds which are
							 | 
						||
| 
								 | 
							
								    supported by the link hardware, as part of this registration operation.
							 | 
						||
| 
								 | 
							
								    Set the desired state of the link to down the next time no tiles are
							 | 
						||
| 
								 | 
							
								    registered for packet reception or transmission.  This flag is ignored
							 | 
						||
| 
								 | 
							
								    if it is specified along with ::NETIO_NO_XMIT and ::NETIO_NO_RECV.
							 | 
						||
| 
								 | 
							
								    See @ref link for more information on link management.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_AUTO_LINK_UPDN   (_NETIO_AUTO_PRESENT | _NETIO_AUTO_UP | \
							 | 
						||
| 
								 | 
							
								                                _NETIO_AUTO_DN)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set the desired state of the link to down the next time no tiles are
							 | 
						||
| 
								 | 
							
								    registered for packet reception or transmission.  This flag is ignored
							 | 
						||
| 
								 | 
							
								    if it is specified along with ::NETIO_NO_XMIT and ::NETIO_NO_RECV.
							 | 
						||
| 
								 | 
							
								    See @ref link for more information on link management.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_AUTO_LINK_DN     (_NETIO_AUTO_PRESENT | _NETIO_AUTO_DN)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Do not bring up the link automatically as part of this registration
							 | 
						||
| 
								 | 
							
								    operation.  Do not take down the link automatically.  This flag
							 | 
						||
| 
								 | 
							
								    is ignored if it is specified along with ::NETIO_NO_XMIT and
							 | 
						||
| 
								 | 
							
								    ::NETIO_NO_RECV.  See @ref link for more information on link management.
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								#define NETIO_AUTO_LINK_NONE   _NETIO_AUTO_PRESENT
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Minimum number of receive packets. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MIN_RECEIVE_PKTS            16
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Lower bound on the maximum number of receive packets; may be higher
							 | 
						||
| 
								 | 
							
								    than this on some interfaces. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MAX_RECEIVE_PKTS           128
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Maximum number of send buffers, per packet size. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MAX_SEND_BUFFERS            16
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Number of EPP queue slots, and thus outstanding sends, per EPP. */
							 | 
						||
| 
								 | 
							
								#define NETIO_TOTAL_SENDS_OUTSTANDING   2015
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Minimum number of EPP queue slots, and thus outstanding sends, per
							 | 
						||
| 
								 | 
							
								 *  transmitting tile. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MIN_SENDS_OUTSTANDING       16
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**@}*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * An object for providing Ethernet packets to a process.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								struct __netio_queue_impl_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * An object for managing the user end of a NetIO queue.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								struct __netio_queue_user_impl_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* !__DOXYGEN__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** A netio_queue_t describes a NetIO communications endpoint.
							 | 
						||
| 
								 | 
							
								 * @ingroup setup
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								  uint8_t opaque[8];                 /**< This is an opaque structure. */
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  struct __netio_queue_impl_t* __system_part;    /**< The system part. */
							 | 
						||
| 
								 | 
							
								  struct __netio_queue_user_impl_t* __user_part; /**< The user part. */
							 | 
						||
| 
								 | 
							
								#ifdef _NETIO_PTHREAD
							 | 
						||
| 
								 | 
							
								  _netio_percpu_mutex_t lock;                    /**< Queue lock. */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_queue_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief Packet send context.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Packet send context for use with netio_send_packet_prepare and _commit.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								  uint8_t opaque[44];   /**< This is an opaque structure. */
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  uint8_t flags;        /**< Defined below */
							 | 
						||
| 
								 | 
							
								  uint8_t datalen;      /**< Number of valid words pointed to by data. */
							 | 
						||
| 
								 | 
							
								  uint32_t request[9];  /**< Request to be sent to the EPP or shim.  Note
							 | 
						||
| 
								 | 
							
								                             that this is smaller than the 11-word maximum
							 | 
						||
| 
								 | 
							
								                             request size, since some constant values are
							 | 
						||
| 
								 | 
							
								                             not saved in the context. */
							 | 
						||
| 
								 | 
							
								  uint32_t *data;       /**< Data to be sent to the EPP or shim via IDN. */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_send_pkt_context_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								#define SEND_PKT_CTX_USE_EPP   1  /**< We're sending to an EPP. */
							 | 
						||
| 
								 | 
							
								#define SEND_PKT_CTX_SEND_CSUM 2  /**< Request includes a checksum. */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief Packet vector entry.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This data structure is used with netio_send_packet_vector() to send multiple
							 | 
						||
| 
								 | 
							
								 * packets with one NetIO call.  The structure should be initialized by
							 | 
						||
| 
								 | 
							
								 * calling netio_pkt_vector_set(), rather than by setting the fields
							 | 
						||
| 
								 | 
							
								 * directly.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This structure is guaranteed to be a power of two in size, no
							 | 
						||
| 
								 | 
							
								 * bigger than one L2 cache line, and to be aligned modulo its size.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								__attribute__((aligned(8)))
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /** Reserved for use by the user application.  When initialized with
							 | 
						||
| 
								 | 
							
								   *  the netio_set_pkt_vector_entry() function, this field is guaranteed
							 | 
						||
| 
								 | 
							
								   *  to be visible to readers only after all other fields are already
							 | 
						||
| 
								 | 
							
								   *  visible.  This way it can be used as a valid flag or generation
							 | 
						||
| 
								 | 
							
								   *  counter. */
							 | 
						||
| 
								 | 
							
								  uint8_t user_data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Structure members below this point should not be accessed directly by
							 | 
						||
| 
								 | 
							
								   * applications, as they may change in the future. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Low 8 bits of the packet address to send.  The high bits are
							 | 
						||
| 
								 | 
							
								   *  acquired from the 'handle' field. */
							 | 
						||
| 
								 | 
							
								  uint8_t buffer_address_low;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of bytes to transmit. */
							 | 
						||
| 
								 | 
							
								  uint16_t size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** The raw handle from a netio_pkt_t.  If this is NETIO_PKT_HANDLE_NONE,
							 | 
						||
| 
								 | 
							
								   *  this vector entry will be skipped and no packet will be transmitted. */
							 | 
						||
| 
								 | 
							
								  netio_pkt_handle_t handle;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_pkt_vector_entry_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief Initialize fields in a packet vector entry.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @ingroup egress
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[out] v Pointer to the vector entry to be initialized.
							 | 
						||
| 
								 | 
							
								 * @param[in] pkt Packet to be transmitted when the vector entry is passed to
							 | 
						||
| 
								 | 
							
								 *        netio_send_packet_vector().  Note that the packet's attributes
							 | 
						||
| 
								 | 
							
								 *        (e.g., its L2 offset and length) are captured at the time this
							 | 
						||
| 
								 | 
							
								 *        routine is called; subsequent changes in those attributes will not
							 | 
						||
| 
								 | 
							
								 *        be reflected in the packet which is actually transmitted.
							 | 
						||
| 
								 | 
							
								 *        Changes in the packet's contents, however, will be so reflected.
							 | 
						||
| 
								 | 
							
								 *        If this is NULL, no packet will be transmitted.
							 | 
						||
| 
								 | 
							
								 * @param[in] user_data User data to be set in the vector entry.
							 | 
						||
| 
								 | 
							
								 *        This function guarantees that the "user_data" field will become
							 | 
						||
| 
								 | 
							
								 *        visible to a reader only after all other fields have become visible.
							 | 
						||
| 
								 | 
							
								 *        This allows a structure in a ring buffer to be written and read
							 | 
						||
| 
								 | 
							
								 *        by a polling reader without any locks or other synchronization.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static __inline void
							 | 
						||
| 
								 | 
							
								netio_pkt_vector_set(volatile netio_pkt_vector_entry_t* v, netio_pkt_t* pkt,
							 | 
						||
| 
								 | 
							
								                     uint8_t user_data)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (pkt)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if (NETIO_PKT_IS_MINIMAL(pkt))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      netio_pkt_minimal_metadata_t* mmd =
							 | 
						||
| 
								 | 
							
								        (netio_pkt_minimal_metadata_t*) &pkt->__metadata;
							 | 
						||
| 
								 | 
							
								      v->buffer_address_low = (uintptr_t) NETIO_PKT_L2_DATA_MM(mmd, pkt) & 0xFF;
							 | 
						||
| 
								 | 
							
								      v->size = NETIO_PKT_L2_LENGTH_MM(mmd, pkt);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      netio_pkt_metadata_t* mda = &pkt->__metadata;
							 | 
						||
| 
								 | 
							
								      v->buffer_address_low = (uintptr_t) NETIO_PKT_L2_DATA_M(mda, pkt) & 0xFF;
							 | 
						||
| 
								 | 
							
								      v->size = NETIO_PKT_L2_LENGTH_M(mda, pkt);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    v->handle.word = pkt->__packet.word;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    v->handle.word = 0;   /* Set handle to NETIO_PKT_HANDLE_NONE. */
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  __asm__("" : : : "memory");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  v->user_data = user_data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Flags and structures for @ref netio_get() and @ref netio_set().
							 | 
						||
| 
								 | 
							
								 * @ingroup config
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** @{ */
							 | 
						||
| 
								 | 
							
								/** Parameter class; addr is a NETIO_PARAM_xxx value. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM       0
							 | 
						||
| 
								 | 
							
								/** Interface MAC address. This address is only valid with @ref netio_get().
							 | 
						||
| 
								 | 
							
								 *  The value is a 6-byte MAC address.  Depending upon the overall system
							 | 
						||
| 
								 | 
							
								 *  design, a MAC address may or may not be available for each interface. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_MAC        0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether to suspend output on the receipt of pause frames.
							 | 
						||
| 
								 | 
							
								 *  If the value is nonzero, the I/O shim will suspend output when a pause
							 | 
						||
| 
								 | 
							
								 *  frame is received.  If the value is zero, pause frames will be ignored. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_PAUSE_IN   1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine whether to send pause frames if the I/O shim packet FIFOs are
							 | 
						||
| 
								 | 
							
								 *  nearly full.  If the value is zero, pause frames are not sent.  If
							 | 
						||
| 
								 | 
							
								 *  the value is nonzero, it is the delay value which will be sent in any
							 | 
						||
| 
								 | 
							
								 *  pause frames which are output, in units of 512 bit times. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_PAUSE_OUT  2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Jumbo frame support.  The value is a 4-byte integer.  If the value is
							 | 
						||
| 
								 | 
							
								 *  nonzero, the MAC will accept frames of up to 10240 bytes.  If the value
							 | 
						||
| 
								 | 
							
								 *  is zero, the MAC will only accept frames of up to 1544 bytes. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_JUMBO      3
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** I/O shim's overflow statistics register.  The value is two 16-bit integers.
							 | 
						||
| 
								 | 
							
								 *  The first 16-bit value (or the low 16 bits, if the value is treated as a
							 | 
						||
| 
								 | 
							
								 *  32-bit number) is the count of packets which were completely dropped and
							 | 
						||
| 
								 | 
							
								 *  not delivered by the shim.  The second 16-bit value (or the high 16 bits,
							 | 
						||
| 
								 | 
							
								 *  if the value is treated as a 32-bit number) is the count of packets
							 | 
						||
| 
								 | 
							
								 *  which were truncated and thus only partially delivered by the shim.  This
							 | 
						||
| 
								 | 
							
								 *  register is automatically reset to zero after it has been read.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_OVERFLOW   4
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** IPP statistics.  This address is only valid with @ref netio_get().  The
							 | 
						||
| 
								 | 
							
								 *  value is a netio_stat_t structure.  Unlike the I/O shim statistics, the
							 | 
						||
| 
								 | 
							
								 *  IPP statistics are not all reset to zero on read; see the description
							 | 
						||
| 
								 | 
							
								 *  of the netio_stat_t for details. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_STAT 5
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Possible link state.  The value is a combination of "NETIO_LINK_xxx"
							 | 
						||
| 
								 | 
							
								 *  flags.  With @ref netio_get(), this will indicate which flags are
							 | 
						||
| 
								 | 
							
								 *  actually supported by the hardware.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  For historical reasons, specifying this value to netio_set() will have
							 | 
						||
| 
								 | 
							
								 *  the same behavior as using ::NETIO_PARAM_LINK_CONFIG, but this usage is
							 | 
						||
| 
								 | 
							
								 *  discouraged.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_LINK_POSSIBLE_STATE 6
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Link configuration. The value is a combination of "NETIO_LINK_xxx" flags.
							 | 
						||
| 
								 | 
							
								 *  With @ref netio_set(), this will attempt to immediately bring up the
							 | 
						||
| 
								 | 
							
								 *  link using whichever of the requested flags are supported by the
							 | 
						||
| 
								 | 
							
								 *  hardware, or take down the link if the flags are zero; if this is
							 | 
						||
| 
								 | 
							
								 *  not possible, an error will be returned.  Many programs will want
							 | 
						||
| 
								 | 
							
								 *  to use ::NETIO_PARAM_LINK_DESIRED_STATE instead.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  For historical reasons, specifying this value to netio_get() will
							 | 
						||
| 
								 | 
							
								 *  have the same behavior as using ::NETIO_PARAM_LINK_POSSIBLE_STATE,
							 | 
						||
| 
								 | 
							
								 *  but this usage is discouraged.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_LINK_CONFIG NETIO_PARAM_LINK_POSSIBLE_STATE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Current link state. This address is only valid with @ref netio_get().
							 | 
						||
| 
								 | 
							
								 *  The value is zero or more of the "NETIO_LINK_xxx" flags, ORed together.
							 | 
						||
| 
								 | 
							
								 *  If the link is down, the value ANDed with NETIO_LINK_SPEED will be
							 | 
						||
| 
								 | 
							
								 *  zero; if the link is up, the value ANDed with NETIO_LINK_SPEED will
							 | 
						||
| 
								 | 
							
								 *  result in exactly one of the NETIO_LINK_xxx values, indicating the
							 | 
						||
| 
								 | 
							
								 *  current speed. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_LINK_CURRENT_STATE 7
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Variant symbol for current state, retained for compatibility with
							 | 
						||
| 
								 | 
							
								 *  pre-MDE-2.1 programs. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_LINK_STATUS NETIO_PARAM_LINK_CURRENT_STATE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Packet Coherence protocol. This address is only valid with @ref netio_get().
							 | 
						||
| 
								 | 
							
								 *  The value is nonzero if the interface is configured for cache-coherent DMA.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_COHERENT 8
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Desired link state. The value is a conbination of "NETIO_LINK_xxx"
							 | 
						||
| 
								 | 
							
								 *  flags, which specify the desired state for the link.  With @ref
							 | 
						||
| 
								 | 
							
								 *  netio_set(), this will, in the background, attempt to bring up the link
							 | 
						||
| 
								 | 
							
								 *  using whichever of the requested flags are reasonable, or take down the
							 | 
						||
| 
								 | 
							
								 *  link if the flags are zero.  The actual link up or down operation may
							 | 
						||
| 
								 | 
							
								 *  happen after this call completes.  If the link state changes in the
							 | 
						||
| 
								 | 
							
								 *  future, the system will continue to try to get back to the desired link
							 | 
						||
| 
								 | 
							
								 *  state; for instance, if the link is brought up successfully, and then
							 | 
						||
| 
								 | 
							
								 *  the network cable is disconnected, the link will go down.  However, the
							 | 
						||
| 
								 | 
							
								 *  desired state of the link is still up, so if the cable is reconnected,
							 | 
						||
| 
								 | 
							
								 *  the link will be brought up again.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  With @ref netio_get(), this will indicate the desired state for the
							 | 
						||
| 
								 | 
							
								 *  link, as set with a previous netio_set() call, or implicitly by a
							 | 
						||
| 
								 | 
							
								 *  netio_input_register() or netio_input_unregister() operation.  This may
							 | 
						||
| 
								 | 
							
								 *  not reflect the current state of the link; to get that, use
							 | 
						||
| 
								 | 
							
								 *  ::NETIO_PARAM_LINK_CURRENT_STATE. */
							 | 
						||
| 
								 | 
							
								#define NETIO_PARAM_LINK_DESIRED_STATE 9
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** NetIO statistics structure.  Retrieved using the ::NETIO_PARAM_STAT
							 | 
						||
| 
								 | 
							
								 *  address passed to @ref netio_get(). */
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /** Number of packets which have been received by the IPP and forwarded
							 | 
						||
| 
								 | 
							
								   *  to a tile's receive queue for processing.  This value wraps at its
							 | 
						||
| 
								 | 
							
								   *  maximum, and is not cleared upon read. */
							 | 
						||
| 
								 | 
							
								  uint32_t packets_received;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of packets which have been dropped by the IPP, because they could
							 | 
						||
| 
								 | 
							
								   *  not be received, or could not be forwarded to a tile.  The former happens
							 | 
						||
| 
								 | 
							
								   *  when the IPP does not have a free packet buffer of suitable size for an
							 | 
						||
| 
								 | 
							
								   *  incoming frame.  The latter happens when all potential destination tiles
							 | 
						||
| 
								 | 
							
								   *  for a packet, as defined by the group, bucket, and queue configuration,
							 | 
						||
| 
								 | 
							
								   *  have full receive queues.   This value wraps at its maximum, and is not
							 | 
						||
| 
								 | 
							
								   *  cleared upon read. */
							 | 
						||
| 
								 | 
							
								  uint32_t packets_dropped;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								   * Note: the #defines after each of the following four one-byte values
							 | 
						||
| 
								 | 
							
								   * denote their location within the third word of the netio_stat_t.  They
							 | 
						||
| 
								 | 
							
								   * are intended for use only by the IPP implementation and are thus omitted
							 | 
						||
| 
								 | 
							
								   * from the Doxygen output.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of packets dropped because no worker was able to accept a new
							 | 
						||
| 
								 | 
							
								   *  packet.  This value saturates at its maximum, and is cleared upon
							 | 
						||
| 
								 | 
							
								   *  read. */
							 | 
						||
| 
								 | 
							
								  uint8_t drops_no_worker;
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								#define NETIO_STAT_DROPS_NO_WORKER   0
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of packets dropped because no small buffers were available.
							 | 
						||
| 
								 | 
							
								   *  This value saturates at its maximum, and is cleared upon read. */
							 | 
						||
| 
								 | 
							
								  uint8_t drops_no_smallbuf;
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								#define NETIO_STAT_DROPS_NO_SMALLBUF 1
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of packets dropped because no large buffers were available.
							 | 
						||
| 
								 | 
							
								   *  This value saturates at its maximum, and is cleared upon read. */
							 | 
						||
| 
								 | 
							
								  uint8_t drops_no_largebuf;
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								#define NETIO_STAT_DROPS_NO_LARGEBUF 2
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /** Number of packets dropped because no jumbo buffers were available.
							 | 
						||
| 
								 | 
							
								   *  This value saturates at its maximum, and is cleared upon read. */
							 | 
						||
| 
								 | 
							
								  uint8_t drops_no_jumbobuf;
							 | 
						||
| 
								 | 
							
								#ifndef __DOXYGEN__
							 | 
						||
| 
								 | 
							
								#define NETIO_STAT_DROPS_NO_JUMBOBUF 3
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_stat_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Link can run, should run, or is running at 10 Mbps. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LINK_10M         0x01
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Link can run, should run, or is running at 100 Mbps. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LINK_100M        0x02
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Link can run, should run, or is running at 1 Gbps. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LINK_1G          0x04
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Link can run, should run, or is running at 10 Gbps. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LINK_10G         0x08
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Link should run at the highest speed supported by the link and by
							 | 
						||
| 
								 | 
							
								 *  the device connected to the link.  Only usable as a value for
							 | 
						||
| 
								 | 
							
								 *  the link's desired state; never returned as a value for the current
							 | 
						||
| 
								 | 
							
								 *  or possible states. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LINK_ANYSPEED    0x10
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** All legal link speeds. */
							 | 
						||
| 
								 | 
							
								#define NETIO_LINK_SPEED  (NETIO_LINK_10M  | \
							 | 
						||
| 
								 | 
							
								                           NETIO_LINK_100M | \
							 | 
						||
| 
								 | 
							
								                           NETIO_LINK_1G   | \
							 | 
						||
| 
								 | 
							
								                           NETIO_LINK_10G  | \
							 | 
						||
| 
								 | 
							
								                           NETIO_LINK_ANYSPEED)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** MAC register class.  Addr is a register offset within the MAC.
							 | 
						||
| 
								 | 
							
								 *  Registers within the XGbE and GbE MACs are documented in the Tile
							 | 
						||
| 
								 | 
							
								 *  Processor I/O Device Guide (UG104). MAC registers start at address
							 | 
						||
| 
								 | 
							
								 *  0x4000, and do not include the MAC_INTERFACE registers. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MAC             1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** MDIO register class (IEEE 802.3 clause 22 format).  Addr is the "addr"
							 | 
						||
| 
								 | 
							
								 *  member of a netio_mdio_addr_t structure. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MDIO            2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** MDIO register class (IEEE 802.3 clause 45 format).  Addr is the "addr"
							 | 
						||
| 
								 | 
							
								 *  member of a netio_mdio_addr_t structure. */
							 | 
						||
| 
								 | 
							
								#define NETIO_MDIO_CLAUSE45   3
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** NetIO MDIO address type.  Retrieved or provided using the ::NETIO_MDIO
							 | 
						||
| 
								 | 
							
								 *  address passed to @ref netio_get() or @ref netio_set(). */
							 | 
						||
| 
								 | 
							
								typedef union
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  struct
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    unsigned int reg:16;  /**< MDIO register offset.  For clause 22 access,
							 | 
						||
| 
								 | 
							
								                               must be less than 32. */
							 | 
						||
| 
								 | 
							
								    unsigned int phy:5;   /**< Which MDIO PHY to access. */
							 | 
						||
| 
								 | 
							
								    unsigned int dev:5;   /**< Which MDIO device to access within that PHY.
							 | 
						||
| 
								 | 
							
								                               Applicable for clause 45 access only; ignored
							 | 
						||
| 
								 | 
							
								                               for clause 22 access. */
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  bits;                   /**< Container for bitfields. */
							 | 
						||
| 
								 | 
							
								  uint64_t addr;          /**< Value to pass to @ref netio_get() or
							 | 
						||
| 
								 | 
							
								                           *   @ref netio_set(). */
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								netio_mdio_addr_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** @} */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* __NETIO_INTF_H__ */
							 |