OpenCores
URL https://opencores.org/ocsvn/1g_ethernet_dpi/1g_ethernet_dpi/trunk

Subversion Repositories 1g_ethernet_dpi

[/] [1g_ethernet_dpi/] [trunk/] [sw/] [dev/] [test_bfm/] [ether/] [ether_tx.c] - Rev 4

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
 
#include "ether.h" // ETH_PKT_MAC_ADDR_LEN, ..
#include "eth_host_bfm.h" // eth_frm_write_wait, ..
 
//////////////////////////////////////////////////////////////////////////////////
// IPv4: name+id LIST
typedef struct {
    char id;
    char name[20];
} ipv4_prot_map_t;
const ipv4_prot_map_t ipv4_prot_map[] = {
    {IPv4_ICMP,         "IPv4_ICMP"}, 
    {IPv4_IGMP,         "IPv4_IGMP"}, 
    {IPv4_TCP,          "IPv4_TCP"}, 
    {IPv4_UDP,          "IPv4_UDP"}, 
    {IPv4_RDP,          "IPv4_RDP"}, 
    {IPv4_IRTP,         "IPv4_IRTP"}, 
    {IPv4_IPv6Encaps,   "IPv4_IPv6Encaps"}, 
    {IPv4_IPv6Route,    "IPv4_IPv6Route"}, 
    {IPv4_IPv6Frag,     "IPv4_IPv6Frag"},
    {IPv4_QNX,          "IPv4_QNX"}, 
    {IPv4_SMP,          "IPv4_SMP"}, 
    {IPv4_SCTP,         "IPv4_SCTP"}, 
    {IPv4_UDPLite,      "IPv4_UDPLite"}
};
//////////////////////////////////////////////////////////////////////////////////
// 
extern unsigned short crc_ip(void * ptr, unsigned count);
extern long crc_ether(char *buf, int len);
 
// 
void ether_tx_raw(char *ibuff, int ilen);
void ether_tx_ipv4(char *ibuff, int ilen);
 
//////////////////////////////////////////////////////////////////////////////////
//
// Ethernet TX routine
//
void ether_tx(char *ibuff, int ilen)
{
    // 
    unsigned short pkt_type = *((unsigned short *)((ibuff)+ETH_PKT_MAC_ADDR_LEN*2));
    switch(pkt_type) {
        case ETH_PKT_ARP : {
            printf("ether_tx: ETH_PKT_ARP, len=%04x\n", ilen);
            ether_tx_raw(ibuff, ilen);
            break;
        }
        case ETH_PKT_IPv4 : {
            ip_hdr_t *ptr_ipv4_hdr = (ip_hdr_t *)(ibuff+ETH_HDR_LEN);
            int i, prot=0;
            for (i = 0; i < (sizeof(ipv4_prot_map))/(sizeof(ipv4_prot_map_t)); i++) {
                if (ipv4_prot_map[i].id == ptr_ipv4_hdr->ip_prot) {
                    printf("ether_tx: %s, len=%04x\n", ipv4_prot_map[i].name, ilen);
                    prot++;
                }
            }
            if (prot == 0) { // not found in list
                printf("ether_tx: ETH_PKT_IPv4: IP protocol number = %x, len=%04x\n", ptr_ipv4_hdr->ip_prot, ilen);
            }
 
            /*
            switch(ptr_ipv4_hdr->ip_prot) {
                case IPv4_ICMP : {
                    printf("ether_tx: ETH_PKT_IPv4-ICMP, len=%04x\n", ilen);
                    break;
                }
                case IPv4_UDP : {
                    printf("ether_tx: ETH_PKT_IPv4-UDP, len=%04x\n", ilen);
                    break;
                }
                default : {
                    printf("ether_tx: ETH_PKT_IPv4: IP protocol number = %x, len=%04x\n", ptr_ipv4_hdr->ip_prot, ilen);
                    break;
                }
            }
            */
            ether_tx_ipv4(ibuff, ilen);
            break;
        }/*
        case ETH_PKT_IPv6 : {
            printf("ether_tx: ETH_PKT_IPv6, len=%04x\n", ilen);
            ether_tx_raw(ibuff, ilen);
        }*/
        default : {
            /*printf("ether_tx: pkt-type=%04x, len=%04x\n", ntohs(pkt_type), ilen);
            ether_tx_raw(ibuff, ilen);*/
            break;
        }
    }
}
//////////////////////////////////////////////////////////////////////////////////
//
// ARP+others
//
void ether_tx_raw(char *ibuff, int ilen)
{
    int i;
    // apr-len == 42 in case if {apr-len < ETH_MIN_TU} -> we will have rejection inside MAC
    int len_raw = (ilen < ETH_MIN_TU)? ETH_MIN_TU : ilen;
    char *ptr_raw = (char *)calloc(len_raw, sizeof(char)); // <- MEM-alloc
    if (ptr_raw == NULL) { return; }
    for (i = 0; i < ETH_MIN_TU; i++) { *(ptr_raw+i) = 0; }
    // data-copy
    for (i = 0; i < ilen; i++) {
        *(ptr_raw+i) = *(ibuff+i);
    }
    // upld
    for (i = 0; i < len_raw; i++) {
        eth_frm_write(*(ptr_raw+i), i);
    }
    // fcs
    int fcs = crc_ether(ptr_raw, len_raw);
    eth_frm_write(((fcs >>  0) & 0xFF), len_raw+0);
    eth_frm_write(((fcs >>  8) & 0xFF), len_raw+1);
    eth_frm_write(((fcs >> 16) & 0xFF), len_raw+2);
    eth_frm_write(((fcs >> 24) & 0xFF), len_raw+3);
    // len + STA
    eth_frm_write_len(len_raw+4); //+ FCS
    // 
    free(ptr_raw); // -> MEM-free
}
//////////////////////////////////////////////////////////////////////////////////
//
// IPv4-UDP
//
void ether_tx_ipv4(char *ibuff, int ilen)
{
    // check len
    char *ptr_ipv4;
    int i, tx_len;
 
    if (ilen < ETH_MIN_TU){
        ptr_ipv4 = (char *)calloc(ETH_MIN_TU, sizeof(char)); // <- MEM-alloc
        if (ptr_ipv4 == NULL) { return; }
        for (i = 0; i < ETH_MIN_TU; i++) { *(ptr_ipv4+i) = 0; }
        for (i = 0; i < ilen; i++) { *(ptr_ipv4+i) = *(ibuff+i); }
        tx_len = ETH_MIN_TU;
    } else {
        ptr_ipv4 = ibuff;
        tx_len = ilen;
    }
 
    // ipv4-csum
    ip_hdr_t *ptr_ipv4_hdr = (ip_hdr_t *)(ibuff+ETH_HDR_LEN);
    ptr_ipv4_hdr->ip_chksum = 0;
    unsigned short ipv4_xsum = ~crc_ip((char *)ptr_ipv4_hdr, ETH_IPv4_HDR_LEN >> 1);
    ptr_ipv4_hdr->ip_chksum = ipv4_xsum;
    // udp-csum
    udp_hdr_t *ptr_udp_hdr = (udp_hdr_t *)(ibuff+ETH_HDR_LEN+ETH_IPv4_HDR_LEN);
    ptr_udp_hdr->ud_cksum = 0;
 
    // upld
    for (i = 0; i < tx_len; i++) {
        eth_frm_write(*(ptr_ipv4+i), i);
    }
    // fcs
    int fcs = crc_ether(ptr_ipv4, tx_len);
    eth_frm_write(((fcs >>  0) & 0xFF), tx_len+0);
    eth_frm_write(((fcs >>  8) & 0xFF), tx_len+1);
    eth_frm_write(((fcs >> 16) & 0xFF), tx_len+2);
    eth_frm_write(((fcs >> 24) & 0xFF), tx_len+3);
    // len + STA
    eth_frm_write_len(tx_len+4); //+ FCS
    // 
    if (ilen < ETH_MIN_TU){
        free(ptr_ipv4); // -> MEM-free
    }
}
//////////////////////////////////////////////////////////////////////////////////
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.