📄 ethernet.c
字号:
// Copyright (C) 2002-2003 Intel Corporation, All Rights Reserved.
// Permission is hereby granted to merge this program code with
// other program material to create a derivative work. This
// derivative work may be distributed in compiled object form only.
// Any other publication of this program, in any form, without the
// explicit permission of the copyright holder is prohibited.
//
// Send questions and comments to erik.j.johnson@intel.com,
// aaron.kunze@intel.com
//-------------------------------------------------------------------
// ethernet.c - Chapter 6
// This file implements functions to process Ethernet II packets.
//
#include <dl_buf.c>
#include <dl_source.h>
#include "ethernet.h"
#include "ethernet_internal.h"
// Some Ethernet basics to be used for validating the packet
// and checking Ethernet fields
#define MIN_ETHERNET_LENGTH 64
#define MAX_ETHERNET_LENGTH 158
#define ETHERNET_ADDR_SIZE 6
#define ETHERNET_HEADER_SIZE 14
// The format of the Ethernet packet header
typedef __declspec(packed) struct _ethernet_header
{
unsigned int destination_addr_hi32;
unsigned int destination_addr_lo16 : 16;
unsigned int source_addr_hi16 : 16;
unsigned int source_addr_lo32;
short protocol;
} ethernet_header;
extern dl_buf_handle_t dlBufHandle;
extern dl_meta_t dlMeta;
extern __declspec(gp_reg) int dlNextBlock;
//-------------------------------------------------------------------
// ethernet_init
//
// Description:
// Sets up any global settings needed to run any of the
// Ethernet functions. This needs to be called only
// once. Right now all it does is set up the hash
// multiplier.
//
// Parameters:
// None.
//
// Side effects: Hash multiplier is set.
//
// See also: n/a
//
// Example Usage: ethernet_init();
//
void ethernet_init()
{
}
//-------------------------------------------------------------------
// ethernet_validate
//
// Description:
// Verifies that the passed in packet is long enough to be an
// Ethernet II packet and has a valid source MAC address.
// Also tells the caller if the packet is addressed to the
// local address, a multicast address, and/or a broadcast
// address. The local address is determined from a place in
// SRAM that is set by the XScale core.
//
// Parameters:
// n/a
//
// Side effects: n/a
//
// See also: n/a
//
// Example Usage: ethernet_validate()
//
void ethernet_validate()
{
ethernet_header header;
int i = 0;
__declspec(sram) ethernet_control_block *control =
(__declspec(sram) ethernet_control_block*)
(ETHERNET_DATA);
// Check the packet length
if (dlMeta.bufferSize < MIN_ETHERNET_LENGTH ||
dlMeta.bufferSize > MAX_ETHERNET_LENGTH)
{
dlNextBlock = ETHERNET_VALIDATE_INVALID;
return;
}
// Now, get the Ethernet header
header = *(__declspec(dram) ethernet_header*)
(Dl_BufGetData(dlBufHandle) +
dlMeta.offset);
/*// Check for a broadcast or multicast source address
if ((header.source_addr_hi16 >> 8) & 0x1)
{
dlNextBlock = ETHERNET_VALIDATE_INVALID;
return;
}
*/
// Check for broadcast or multicast destination address
if ((header.destination_addr_hi32 >> 24) & 0x1)
{
if (header.destination_addr_hi32 != 0xffffffff &&
header.destination_addr_lo16 != 0xffff)
{
dlNextBlock = ETHERNET_VALIDATE_MULTICAST;
return;
}
dlNextBlock = ETHERNET_VALIDATE_BROADCAST;
return;
}
// Check to see if the packet is locally addressed
/* if (header.destination_addr_hi32 !=
control->device_addr_hi32 &&
header.destination_addr_lo16 !=
control->device_addr_lo16)
{
dlNextBlock = ETHERNET_VALIDATE_OTHER;
return;
}
*/
dlNextBlock = ETHERNET_VALIDATE_LOCAL;
return;
}
//-------------------------------------------------------------------
// ethernet_strip_header
//
// Description:
// Removes the Ethernet header from the packet puts
// the Ethernet protocol number in dl_next_block.
//
// Parameters:
// n/a
//
// Side effects: n/a
//
// See also: n/a
//
// Example Usage: ethernet_strip_header();
//
void ethernet_strip_header()
{
ethernet_header header;
// Get the ethernet header so we can extract the
// protocol
header = *(__declspec(dram) ethernet_header*)
(Dl_BufGetData(dlBufHandle) +
dlMeta.offset);
dlNextBlock = header.protocol;
// Adjust the pointer and length
dlMeta.bufferSize -= ETHERNET_HEADER_SIZE;
dlMeta.offset += ETHERNET_HEADER_SIZE;
}
//-------------------------------------------------------------------
// ethernet_add_header
//
// Description:
// Adds an Ethernet header to an IP packet. This function uses
// the next hop ID as an index into a table and retrieves a MAC
// address to put in the destination address of the Ethernet
// packet. The source MAC address is set to the MAC address of
// the device. The Ethernet protocol number is passed in.
//
// Parameters:
// Inputs: eth_proto The Ethernet protocol number
// to insert in the packet.
// Constants: n/a
// Labels: n/a
//
// Side effects: n/a
//
// See also: n/a
//
// Example Usage: ethernet_add_header(ETH_PROTO_IP)
//
void ethernet_add_header(unsigned int eth_proto)
{
ethernet_arp_table_entry table_entry;
__declspec(sram) ethernet_control_block *control =
(__declspec(sram) ethernet_control_block*)
(ETHERNET_DATA);
unsigned int eth_address_hi32;
unsigned int eth_address_lo16;
bool found = 0;
volatile __declspec(dram) ethernet_header*
header;
//ethernet_header header;
// Look up the next hop IP address in the array
// in memory, using the next hop ID as the index.
table_entry =
control->arp_table_array[dlMeta.nextHopId];
// If the entry is not valid, drop this packet.
if (!table_entry.valid)
{
//dl_set_exception(ETHERNET_EXCEPTION_ID ,0);
dlNextBlock = IX_EXCEPTION;
return;
}
eth_address_hi32 =
table_entry.ethernet_address_hi32;
eth_address_lo16 =
table_entry.ethernet_address_lo16;
// Since we found a MAC address, we can add the
// header
dlMeta.bufferSize += ETHERNET_HEADER_SIZE;
dlMeta.offset -= ETHERNET_HEADER_SIZE;
header = (__declspec(dram) ethernet_header*)
(Dl_BufGetData(dlBufHandle) +
dlMeta.offset);
// Set the destination address in the header to be
// the Ethernet address from the table.
header->destination_addr_hi32 = eth_address_hi32;
header->destination_addr_lo16 = eth_address_lo16;
// Set the source address to be the device's MAC
// address
header->source_addr_hi16 =
control->device_addr_hi32 >> 16;
header->source_addr_lo32 =
(control->device_addr_hi32 << 16) |
(control->device_addr_lo16);
// Set the protocol number to be the passed in
// protocol number
header->protocol = eth_proto;
dlNextBlock = ETHERNET_ADD_HEADER_PASS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -