libnet/microudp: (WIP) fix endianness issues
This commit is contained in:
parent
d9d0320d7c
commit
26963d62fa
|
@ -136,7 +136,7 @@ class MiniSoC(BaseSoC):
|
||||||
|
|
||||||
self.submodules.ethphy = LiteEthPHYMII(self.platform.request("eth_clocks"),
|
self.submodules.ethphy = LiteEthPHYMII(self.platform.request("eth_clocks"),
|
||||||
self.platform.request("eth"))
|
self.platform.request("eth"))
|
||||||
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone")
|
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone", endianness="little")
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
|
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
|
||||||
self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
|
self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* Copyright © 2005-2014 Rich Felker, et al.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INET_H
|
||||||
|
#define __INET_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static __inline uint16_t __bswap_16(uint16_t __x)
|
||||||
|
{
|
||||||
|
return (__x<<8) | (__x>>8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline uint32_t __bswap_32(uint32_t __x)
|
||||||
|
{
|
||||||
|
return (__x>>24) | ((__x>>8)&0xff00) | ((__x<<8)&0xff0000) | (__x<<24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline uint64_t __bswap_64(uint64_t __x)
|
||||||
|
{
|
||||||
|
return (__bswap_32(__x)+(0ULL<<32)) | __bswap_32(__x>>32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define bswap_16(x) __bswap_16(x)
|
||||||
|
#define bswap_32(x) __bswap_32(x)
|
||||||
|
#define bswap_64(x) __bswap_64(x)
|
||||||
|
|
||||||
|
uint16_t htons(uint16_t n);
|
||||||
|
uint32_t htonl(uint32_t n);
|
||||||
|
uint16_t ntohs(uint16_t n);
|
||||||
|
uint32_t ntohl(uint32_t n);
|
||||||
|
|
||||||
|
#endif /* __INET_H */
|
|
@ -22,6 +22,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <inet.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* strchr - Find the first occurrence of a character in a string
|
* strchr - Find the first occurrence of a character in a string
|
||||||
|
@ -732,3 +733,27 @@ void abort(void)
|
||||||
printf("Aborted.");
|
printf("Aborted.");
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t htonl(uint32_t n)
|
||||||
|
{
|
||||||
|
union { int i; char c; } u = { 1 };
|
||||||
|
return u.c ? bswap_32(n) : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t htons(uint16_t n)
|
||||||
|
{
|
||||||
|
union { int i; char c; } u = { 1 };
|
||||||
|
return u.c ? bswap_16(n) : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ntohl(uint32_t n)
|
||||||
|
{
|
||||||
|
union { int i; char c; } u = { 1 };
|
||||||
|
return u.c ? bswap_32(n) : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ntohs(uint16_t n)
|
||||||
|
{
|
||||||
|
union { int i; char c; } u = { 1 };
|
||||||
|
return u.c ? bswap_16(n) : n;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#ifdef CSR_ETHMAC_BASE
|
#ifdef CSR_ETHMAC_BASE
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <inet.h>
|
||||||
#include <system.h>
|
#include <system.h>
|
||||||
#include <crc.h>
|
#include <crc.h>
|
||||||
#include <hw/flags.h>
|
#include <hw/flags.h>
|
||||||
|
@ -41,7 +42,7 @@ static void fill_eth_header(struct ethernet_header *h, const unsigned char *dest
|
||||||
h->destmac[i] = destmac[i];
|
h->destmac[i] = destmac[i];
|
||||||
for(i=0;i<6;i++)
|
for(i=0;i<6;i++)
|
||||||
h->srcmac[i] = srcmac[i];
|
h->srcmac[i] = srcmac[i];
|
||||||
h->ethertype = ethertype;
|
h->ethertype = htons(ethertype);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARP_HWTYPE_ETHERNET 0x0001
|
#define ARP_HWTYPE_ETHERNET 0x0001
|
||||||
|
@ -133,8 +134,9 @@ static void send_packet(void)
|
||||||
txbuffer->raw[txlen+1] = (crc & 0xff00) >> 8;
|
txbuffer->raw[txlen+1] = (crc & 0xff00) >> 8;
|
||||||
txbuffer->raw[txlen+2] = (crc & 0xff0000) >> 16;
|
txbuffer->raw[txlen+2] = (crc & 0xff0000) >> 16;
|
||||||
txbuffer->raw[txlen+3] = (crc & 0xff000000) >> 24;
|
txbuffer->raw[txlen+3] = (crc & 0xff000000) >> 24;
|
||||||
txlen += 4;
|
//txlen += 4;
|
||||||
#endif
|
#endif
|
||||||
|
txlen += 4; // FIXME
|
||||||
|
|
||||||
#ifdef DEBUG_MICROUDP_TX
|
#ifdef DEBUG_MICROUDP_TX
|
||||||
int j;
|
int j;
|
||||||
|
@ -167,21 +169,22 @@ static void process_arp(void)
|
||||||
const struct arp_frame *rx_arp = &rxbuffer->frame.contents.arp;
|
const struct arp_frame *rx_arp = &rxbuffer->frame.contents.arp;
|
||||||
struct arp_frame *tx_arp = &txbuffer->frame.contents.arp;
|
struct arp_frame *tx_arp = &txbuffer->frame.contents.arp;
|
||||||
|
|
||||||
if(rxlen < ARP_PACKET_LENGTH) return;
|
//if(rxlen < ARP_PACKET_LENGTH) return; // FIXME
|
||||||
if(rx_arp->hwtype != ARP_HWTYPE_ETHERNET) return;
|
if(ntohs(rx_arp->hwtype) != ARP_HWTYPE_ETHERNET) return;
|
||||||
if(rx_arp->proto != ARP_PROTO_IP) return;
|
if(ntohs(rx_arp->proto) != ARP_PROTO_IP) return;
|
||||||
if(rx_arp->hwsize != 6) return;
|
if(rx_arp->hwsize != 6) return;
|
||||||
if(rx_arp->protosize != 4) return;
|
if(rx_arp->protosize != 4) return;
|
||||||
if(rx_arp->opcode == ARP_OPCODE_REPLY) {
|
|
||||||
if(rx_arp->sender_ip == cached_ip) {
|
if(ntohs(rx_arp->opcode) == ARP_OPCODE_REPLY) {
|
||||||
|
if(ntohl(rx_arp->sender_ip) == cached_ip) {
|
||||||
int i;
|
int i;
|
||||||
for(i=0;i<6;i++)
|
for(i=0;i<6;i++)
|
||||||
cached_mac[i] = rx_arp->sender_mac[i];
|
cached_mac[i] = rx_arp->sender_mac[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(rx_arp->opcode == ARP_OPCODE_REQUEST) {
|
if(ntohs(rx_arp->opcode) == ARP_OPCODE_REQUEST) {
|
||||||
if(rx_arp->target_ip == my_ip) {
|
if(ntohl(rx_arp->target_ip) == my_ip) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fill_eth_header(&txbuffer->frame.eth_header,
|
fill_eth_header(&txbuffer->frame.eth_header,
|
||||||
|
@ -189,15 +192,15 @@ static void process_arp(void)
|
||||||
my_mac,
|
my_mac,
|
||||||
ETHERTYPE_ARP);
|
ETHERTYPE_ARP);
|
||||||
txlen = ARP_PACKET_LENGTH;
|
txlen = ARP_PACKET_LENGTH;
|
||||||
tx_arp->hwtype = ARP_HWTYPE_ETHERNET;
|
tx_arp->hwtype = htons(ARP_HWTYPE_ETHERNET);
|
||||||
tx_arp->proto = ARP_PROTO_IP;
|
tx_arp->proto = htons(ARP_PROTO_IP);
|
||||||
tx_arp->hwsize = 6;
|
tx_arp->hwsize = 6;
|
||||||
tx_arp->protosize = 4;
|
tx_arp->protosize = 4;
|
||||||
tx_arp->opcode = ARP_OPCODE_REPLY;
|
tx_arp->opcode = htons(ARP_OPCODE_REPLY);
|
||||||
tx_arp->sender_ip = my_ip;
|
tx_arp->sender_ip = htonl(my_ip);
|
||||||
for(i=0;i<6;i++)
|
for(i=0;i<6;i++)
|
||||||
tx_arp->sender_mac[i] = my_mac[i];
|
tx_arp->sender_mac[i] = my_mac[i];
|
||||||
tx_arp->target_ip = rx_arp->sender_ip;
|
tx_arp->target_ip = htonl(ntohl(rx_arp->sender_ip));
|
||||||
for(i=0;i<6;i++)
|
for(i=0;i<6;i++)
|
||||||
tx_arp->target_mac[i] = rx_arp->sender_mac[i];
|
tx_arp->target_mac[i] = rx_arp->sender_mac[i];
|
||||||
send_packet();
|
send_packet();
|
||||||
|
@ -210,7 +213,7 @@ static const unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
int microudp_arp_resolve(unsigned int ip)
|
int microudp_arp_resolve(unsigned int ip)
|
||||||
{
|
{
|
||||||
struct arp_frame *arp = &txbuffer->frame.contents.arp;
|
struct arp_frame *arp;
|
||||||
int i;
|
int i;
|
||||||
int tries;
|
int tries;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
@ -230,17 +233,19 @@ int microudp_arp_resolve(unsigned int ip)
|
||||||
my_mac,
|
my_mac,
|
||||||
ETHERTYPE_ARP);
|
ETHERTYPE_ARP);
|
||||||
txlen = ARP_PACKET_LENGTH;
|
txlen = ARP_PACKET_LENGTH;
|
||||||
arp->hwtype = ARP_HWTYPE_ETHERNET;
|
arp = &txbuffer->frame.contents.arp;
|
||||||
arp->proto = ARP_PROTO_IP;
|
arp->hwtype = htons(ARP_HWTYPE_ETHERNET);
|
||||||
|
arp->proto = htons(ARP_PROTO_IP);
|
||||||
arp->hwsize = 6;
|
arp->hwsize = 6;
|
||||||
arp->protosize = 4;
|
arp->protosize = 4;
|
||||||
arp->opcode = ARP_OPCODE_REQUEST;
|
arp->opcode = htons(ARP_OPCODE_REQUEST);
|
||||||
arp->sender_ip = my_ip;
|
arp->sender_ip = htonl(my_ip);
|
||||||
for(i=0;i<6;i++)
|
for(i=0;i<6;i++)
|
||||||
arp->sender_mac[i] = my_mac[i];
|
arp->sender_mac[i] = my_mac[i];
|
||||||
arp->target_ip = ip;
|
arp->target_ip = htonl(ip);
|
||||||
for(i=0;i<6;i++)
|
for(i=0;i<6;i++)
|
||||||
arp->target_mac[i] = 0;
|
arp->target_mac[i] = 0;
|
||||||
|
|
||||||
send_packet();
|
send_packet();
|
||||||
|
|
||||||
/* Do we get a reply ? */
|
/* Do we get a reply ? */
|
||||||
|
@ -309,20 +314,20 @@ int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int
|
||||||
|
|
||||||
txbuffer->frame.contents.udp.ip.version = IP_IPV4;
|
txbuffer->frame.contents.udp.ip.version = IP_IPV4;
|
||||||
txbuffer->frame.contents.udp.ip.diff_services = 0;
|
txbuffer->frame.contents.udp.ip.diff_services = 0;
|
||||||
txbuffer->frame.contents.udp.ip.total_length = length + sizeof(struct udp_frame);
|
txbuffer->frame.contents.udp.ip.total_length = htons(length + sizeof(struct udp_frame));
|
||||||
txbuffer->frame.contents.udp.ip.identification = 0;
|
txbuffer->frame.contents.udp.ip.identification = htons(0);
|
||||||
txbuffer->frame.contents.udp.ip.fragment_offset = IP_DONT_FRAGMENT;
|
txbuffer->frame.contents.udp.ip.fragment_offset = htons(IP_DONT_FRAGMENT);
|
||||||
txbuffer->frame.contents.udp.ip.ttl = IP_TTL;
|
txbuffer->frame.contents.udp.ip.ttl = IP_TTL;
|
||||||
h.proto = txbuffer->frame.contents.udp.ip.proto = IP_PROTO_UDP;
|
h.proto = txbuffer->frame.contents.udp.ip.proto = IP_PROTO_UDP;
|
||||||
txbuffer->frame.contents.udp.ip.checksum = 0;
|
txbuffer->frame.contents.udp.ip.checksum = 0;
|
||||||
h.src_ip = txbuffer->frame.contents.udp.ip.src_ip = my_ip;
|
h.src_ip = txbuffer->frame.contents.udp.ip.src_ip = htonl(my_ip);
|
||||||
h.dst_ip = txbuffer->frame.contents.udp.ip.dst_ip = cached_ip;
|
h.dst_ip = txbuffer->frame.contents.udp.ip.dst_ip = htonl(cached_ip);
|
||||||
txbuffer->frame.contents.udp.ip.checksum = ip_checksum(0, &txbuffer->frame.contents.udp.ip,
|
txbuffer->frame.contents.udp.ip.checksum = htons(ip_checksum(0, &txbuffer->frame.contents.udp.ip,
|
||||||
sizeof(struct ip_header), 1);
|
sizeof(struct ip_header), 1));
|
||||||
|
|
||||||
txbuffer->frame.contents.udp.udp.src_port = src_port;
|
txbuffer->frame.contents.udp.udp.src_port = htons(src_port);
|
||||||
txbuffer->frame.contents.udp.udp.dst_port = dst_port;
|
txbuffer->frame.contents.udp.udp.dst_port = htons(dst_port);
|
||||||
h.length = txbuffer->frame.contents.udp.udp.length = length + sizeof(struct udp_header);
|
h.length = txbuffer->frame.contents.udp.udp.length = htons(length + sizeof(struct udp_header));
|
||||||
txbuffer->frame.contents.udp.udp.checksum = 0;
|
txbuffer->frame.contents.udp.udp.checksum = 0;
|
||||||
|
|
||||||
h.zero = 0;
|
h.zero = 0;
|
||||||
|
@ -333,7 +338,7 @@ int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int
|
||||||
}
|
}
|
||||||
r = ip_checksum(r, &txbuffer->frame.contents.udp.udp,
|
r = ip_checksum(r, &txbuffer->frame.contents.udp.udp,
|
||||||
sizeof(struct udp_header)+length, 1);
|
sizeof(struct udp_header)+length, 1);
|
||||||
txbuffer->frame.contents.udp.udp.checksum = r;
|
txbuffer->frame.contents.udp.udp.checksum = htons(r);
|
||||||
|
|
||||||
send_packet();
|
send_packet();
|
||||||
|
|
||||||
|
@ -345,19 +350,21 @@ static udp_callback rx_callback;
|
||||||
static void process_ip(void)
|
static void process_ip(void)
|
||||||
{
|
{
|
||||||
if(rxlen < (sizeof(struct ethernet_header)+sizeof(struct udp_frame))) return;
|
if(rxlen < (sizeof(struct ethernet_header)+sizeof(struct udp_frame))) return;
|
||||||
|
struct udp_frame *udp_ip = &rxbuffer->frame.contents.udp;
|
||||||
/* We don't verify UDP and IP checksums and rely on the Ethernet checksum solely */
|
/* We don't verify UDP and IP checksums and rely on the Ethernet checksum solely */
|
||||||
if(rxbuffer->frame.contents.udp.ip.version != IP_IPV4) return;
|
if(udp_ip->ip.version != IP_IPV4) return;
|
||||||
// check disabled for QEMU compatibility
|
// check disabled for QEMU compatibility
|
||||||
//if(rxbuffer->frame.contents.udp.ip.diff_services != 0) return;
|
//if(rxbuffer->frame.contents.udp.ip.diff_services != 0) return;
|
||||||
if(rxbuffer->frame.contents.udp.ip.total_length < sizeof(struct udp_frame)) return;
|
if(ntohs(udp_ip->ip.total_length) < sizeof(struct udp_frame)) return;
|
||||||
// check disabled for QEMU compatibility
|
// check disabled for QEMU compatibility
|
||||||
//if(rxbuffer->frame.contents.udp.ip.fragment_offset != IP_DONT_FRAGMENT) return;
|
//if(ntohs(rxbuffer->frame.contents.udp.ip.fragment_offset) != IP_DONT_FRAGMENT) return;
|
||||||
if(rxbuffer->frame.contents.udp.ip.proto != IP_PROTO_UDP) return;
|
if(udp_ip->ip.proto != IP_PROTO_UDP) return;
|
||||||
if(rxbuffer->frame.contents.udp.ip.dst_ip != my_ip) return;
|
if(ntohl(udp_ip->ip.dst_ip) != my_ip) return;
|
||||||
if(rxbuffer->frame.contents.udp.udp.length < sizeof(struct udp_header)) return;
|
if(ntohs(udp_ip->udp.length) < sizeof(struct udp_header)) return;
|
||||||
|
|
||||||
if(rx_callback)
|
if(rx_callback)
|
||||||
rx_callback(rxbuffer->frame.contents.udp.ip.src_ip, rxbuffer->frame.contents.udp.udp.src_port, rxbuffer->frame.contents.udp.udp.dst_port, rxbuffer->frame.contents.udp.payload, rxbuffer->frame.contents.udp.udp.length-sizeof(struct udp_header));
|
rx_callback(ntohl(udp_ip->ip.src_ip), ntohs(udp_ip->udp.src_port), ntohs(udp_ip->udp.dst_port),
|
||||||
|
udp_ip->payload, ntohs(udp_ip->udp.length)-sizeof(struct udp_header));
|
||||||
}
|
}
|
||||||
|
|
||||||
void microudp_set_callback(udp_callback callback)
|
void microudp_set_callback(udp_callback callback)
|
||||||
|
@ -397,8 +404,8 @@ static void process_frame(void)
|
||||||
rxlen -= 4; /* strip CRC here to be consistent with TX */
|
rxlen -= 4; /* strip CRC here to be consistent with TX */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(rxbuffer->frame.eth_header.ethertype == ETHERTYPE_ARP) process_arp();
|
if(ntohs(rxbuffer->frame.eth_header.ethertype) == ETHERTYPE_ARP) process_arp();
|
||||||
else if(rxbuffer->frame.eth_header.ethertype == ETHERTYPE_IP) process_ip();
|
else if(ntohs(rxbuffer->frame.eth_header.ethertype) == ETHERTYPE_IP) process_ip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void microudp_start(const unsigned char *macaddr, unsigned int ip)
|
void microudp_start(const unsigned char *macaddr, unsigned int ip)
|
||||||
|
|
Loading…
Reference in New Issue