Hello,
few years ago I have tried to test lwip on my Linux machine. There are
some demos in LWIP directory but for me I have used the tap device
binded with the eth interface. All packets read from tap were forwared
to the LWIP and vice versa. See the attached file as a reference (the
unknown language inside is Czech).
BR
Martin
On Wed, Apr 27, 2016 at 5:10 PM, Zhuoran Zhao <[email protected]> wrote:
> Hello all,
>
> I am currently using raspberry pi 3 (running ubuntu MATE) as a reference
> platform and trying to get some performance data out of it. Besides using
> TAP/TUN device and wlan bridging to port the lwip, I am wondering is there
> any open source lwip port for raspberry pi 3 making use of the on board
> network interface driver?
>
> Any suggestions/raspberry porting experiences will be helpful, thanks!
>
>
>
> --
> Zhuoran Zhao
> Computer Engineering Research Center (CERC), University of Texas at Austin,
> Department of Electrical and Computer Engineering, University of Texas at
> Austin,
> Cellphone: (+1)512-751-1819
> Email: [email protected]
> Skype: zhuoran.zhao
>
>
> _______________________________________________
> lwip-users mailing list
> [email protected]
> https://lists.nongnu.org/mailman/listinfo/lwip-users
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <error.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "../log/logger.h"
#include <glib.h>
#include "simulator_ethernet.h"
#define ETH_ENABLE_DEBUG_LOG 0
#define ETH_REAL 0
#define ETH_TAP 1
#define ETH_TYPE ETH_TAP
/* see linux/if_ether.h */
#define ETH_MAC_LEN ETH_ALEN /* Octets in one ethernet addr */
#define ETH_HEADER_LEN ETH_HLEN /* Total octets in header. */
#define ETH_MIN_FRAME_LEN ETH_ZLEN /* Min. octets in frame sans FCS */
#define ETH_USER_DATA_LEN ETH_DATA_LEN /* Max. octets in payload */
#define ETH_MAX_FRAME_LEN ETH_FRAME_LEN /* Max. octets in frame sans FCS */
#define ETH_FRAME_TOTALLEN 1518 /*Header: 14 + User Data: 1500 FCS: 4*/
#define ETH_P_NULL 0x0 /* we are running without any protocol
above the Ethernet Layer*/
#define BUF_SIZE ETH_FRAME_TOTALLEN
// Status of peripheral physical
static uint32_t peripheral_psysical_status = 0;
// eth communincation socket
static int eth_socket = -1;
static __inline__ int min(int x, int y)
{
return (x < y ? x : y);
}
#if (ETH_TYPE == ETH_REAL)
static int ifindex = -1; /*Ethernet Interface index*/
uint8_t src_mac[6]; /*our MAC address*/
uint8_t output_mac[6]; /*modified src MAC address for GTK simulator*/
static struct sockaddr_ll socket_address; // used for binding 802.2
static void ethernet_shutdown(void)
{
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = ifindex;
mr.mr_type = PACKET_MR_PROMISC;
setsockopt(eth_socket, SOL_PACKET, PACKET_DROP_MEMBERSHIP, (char *)
&mr, sizeof(mr));
}
static int ethernet_communication_receive(int socket, void * buffer, size_t len)
{
struct sockaddr_ll addr;
size_t size = sizeof(addr);
int received;
memset(&addr, 0, sizeof(addr));
received = recvfrom(socket, buffer, len, 0, (struct sockaddr *) &addr,
&size);
if (received < 0)
{
logger_fmt("ETH error during recvfrom()");
}
else
{
// Check the destination address. If not for us, do not store
packet to save LIMA - GTK channel.
struct ethhdr *eh = (struct ethhdr *) buffer;
/*
PACKET_HOST – rámec je určen jen pro tento počítač.
PACKET_BROADCAST – rámec je vyslán broadcastem. Je určen pro
všechny.
PACKET_MULTICAST – rámec je vyslán multicastem. Je určen pro
skupinu.
PACKET_OTHERHOST – rámec je určen pro jiný počítač. Naším
síťovým rozhraním byl přijat jen díky nastavení promiskuitního režimu.
PACKET_OUTGOING – tento rámec se mi nepodařilo v mých
experimenech přijmout.
*/
switch (addr.sll_pkttype)
{
case PACKET_OUTGOING:
{
// Do not receive packets sent to this interface back.
logger_fmt("ETH PACKET_OUTGOING():");
received = 0;
break;
}
case PACKET_BROADCAST:
{
logger_fmt("ETH PACKET_BROADCAST():");
break;
}
case PACKET_MULTICAST:
{
logger_fmt("ETH PACKET_MULTICAST():");
break;
}
case PACKET_OTHERHOST:
{
logger_fmt("ETH PACKET_OTHERHOST():");
// Is it our packet?
if (0 != memcmp(eh->h_dest, output_mac, ETH_ALEN))
{
#if 0
logger_fmt("ETH received from ethx %d",
received);
logger_fmt("source MAC address:
%02X:%02X:%02X:%02X:%02X:%02X\n", eh->h_source[0], eh->h_source[1],
eh->h_source[2], eh->h_source[3],
eh->h_source[4],
eh->h_source[5]);
logger_fmt("Destination MAC address:
%02X:%02X:%02X:%02X:%02X:%02X\n", eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
eh->h_dest[3],
eh->h_dest[4], eh->h_dest[5]);
logger_fmt("Packet type: %x ", eh->h_proto);
#endif
logger_fmt("ETH packet not for us");
received = 0;
}
break;
}
case PACKET_HOST:
{
// Do not receive packets sent to host interface.
logger_fmt("ETH PACKET_HOST():");
received = 0;
break;
}
default:
{
logger_fmt("ETH unsupported addr.sll_pkttype %d",
addr.sll_pkttype);
received = 0;
break;
}
}
#if 0
logger_fmt("ETH received from ethx %d", received);
logger_fmt("source MAC address:
%02X:%02X:%02X:%02X:%02X:%02X\n",
eh->h_source[0], eh->h_source[1],
eh->h_source[2],
eh->h_source[3], eh->h_source[4],
eh->h_source[5]);
logger_fmt("Destination MAC address:
%02X:%02X:%02X:%02X:%02X:%02X\n",
eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
eh->h_dest[3],
eh->h_dest[4], eh->h_dest[5]);
logger_fmt("Packet type: %x ", eh->h_proto);
#endif
}
return received;
}
// Thread to create sdl screent and handle mouse events.
static gpointer ethernet_receive_thread(gpointer data)
{
uint8_t ethernet_data[BUF_SIZE];
int received_size;
#if 0
struct pollfd fds[1];
fds[0].fd = eth_socket;
fds[0].events = POLLIN;
rv = poll(fds, 1, 2000);
if ((rv > 0) && (fds[0].revents & POLLIN))
#endif
logger_fmt("ETH receive thread started");
for (;;)
{
received_size = ethernet_communication_receive(eth_socket,
ethernet_data, BUF_SIZE);
if (received_size > 0)
{
if ((peripheral_psysical_status & (1U << 0)))
{
simulator_send_message(0xEEEE, PERIPHERAL_EMAC,
0, HAL_EMAC_INDEX_SEND_FRAME, ethernet_data, received_size);
}
else
{
logger_fmt("ETH device 0 is not enabled yet");
}
}
}
return 0;
}
int ethernet_communication_init(const char * device)
{
int s = 0; /*Socketdescriptor*/
struct ifreq ifr;
if ((0 != getuid()) || (0 != geteuid()))
{
logger_fmt("ETH Stronger permission required, you must be at
least root\n");
}
/*open socket*/
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1)
{
logger_fmt("ETH socket():");
return s;
}
/*retrieve ethernet interface index*/
strncpy(ifr.ifr_name, device, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1)
{
logger_fmt("ETH SIOCGIFINDEX");
return -1;
}
ifindex = ifr.ifr_ifindex;
/*retrieve corresponding MAC*/
if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1)
{
logger_fmt("ETH SIOCGIFINDEX");
return -1;
}
logger_fmt("ETH Successfully got interface index: %i\n", ifindex);
// Copy mac.
for (int i = 0; i < 6; i++)
{
output_mac[i] = src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
}
logger_fmt("ETH Successfully got our MAC address:
%02X:%02X:%02X:%02X:%02X:%02X\n", src_mac[0], src_mac[1], src_mac[2],
src_mac[3], src_mac[4], src_mac[5]);
// Set MAC to be a locally administrated - bit 1 of mac addr.
output_mac[0] |= 1U << 1;
logger_fmt("ETH New MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
output_mac[0], output_mac[1], output_mac[2], output_mac[3], output_mac[4],
output_mac[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ALL);
socket_address.sll_ifindex = ifindex;
if (bind(s, (struct sockaddr *) &socket_address,
sizeof(socket_address)) == -1)
{
logger_fmt("ETH Bind failed");
;
return -1;
}
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = ifindex;
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(s, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *) &mr,
sizeof(mr)) == -1)
{
logger_fmt("ETH setsockopt() failed");
}
// Assign socket.
eth_socket = s;
// create receive thread.
g_thread_create(ethernet_receive_thread, NULL, FALSE, NULL );
// OK.
logger_fmt("ETH %s initialized", device);
// drop membership at exit.
atexit(ethernet_shutdown);
return s;
}
#endif
#if (ETH_TYPE == ETH_TAP)
static void ethernet_shutdown(void)
{
// just close the socket
close(eth_socket);
}
static ssize_t ethernet_communication_receive(int socket, void * buffer, size_t
len)
{
ssize_t received;
received = read(socket, buffer, len);
if (received < 0)
{
logger_fmt("ETH error during socket read(), %s",
strerror(errno));
}
return received;
}
// Thread to create sdl screent and handle mouse events.
static gpointer ethernet_receive_thread(gpointer data)
{
uint8_t ethernet_data[BUF_SIZE];
ssize_t received_size;
int socketfd = GPOINTER_TO_INT(data);
logger_fmt("ETH receive thread started");
for (;;)
{
received_size = ethernet_communication_receive(socketfd,
ethernet_data, BUF_SIZE);
if (received_size > 0)
{
if ((peripheral_psysical_status & (1U << 0)))
{
simulator_send_message(0xEEEEU,
PERIPHERAL_EMAC, 0, HAL_EMAC_INDEX_SEND_FRAME, ethernet_data,
(size_t)received_size);
}
else
{
logger_fmt("ETH device 0 is not enabled yet");
}
}
}
return 0;
}
int ethernet_communication_init(const char * device)
{
struct ifreq ifr;
int fd, err;
char *clonedev = "/dev/net/tun";
/* open the clone device */
if( (fd = open(clonedev, O_RDWR)) < 0 ) {
perror("open clonedev");
return fd;
}
/* preparation of the struct ifr, of type "struct ifreq" */
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* IFF_TUN or IFF_TAP, plus
maybe IFF_NO_PI */
if (*device) {
/* if a device name was specified, put it in the structure;
otherwise,
* the kernel will try to allocate the "next" device of the
* specified type */
strncpy(ifr.ifr_name, device, IFNAMSIZ);
}
/* try to create the device */
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
perror("open ioctl clonedev");
close(fd);
return err;
}
// Assign socket.
eth_socket = fd;
// create receive thread.
g_thread_create(ethernet_receive_thread, GINT_TO_POINTER(eth_socket),
FALSE, NULL );
// OK.
logger_fmt("ETH %s initialized", device);
// drop membership at exit.
atexit(ethernet_shutdown);
return fd;
}
#endif
static ssize_t ethernet_communication_send(int socket, const void * buffer,
size_t len)
{
ssize_t sent;
sent = write(socket, buffer, len);
if (sent < 0)
{
logger_fmt("ETH send to socket failed: %s", strerror(errno));
}
return sent;
}
void ethernet_communication_handler(uint8_t peripheral_id, uint8_t
peripheral_number, const struct SYSTEM_SIMULATOR_PROTOCOL * lsp)
{
if (PERIPHERAL_EMAC != peripheral_id)
{
logger_fmt("ETH peripheral_id %d does not match to
PERIPHERAL_EMAC", peripheral_id);
return;
}
if (!(peripheral_psysical_status & (1U << peripheral_number)))
{
logger_fmt("ETH peripheral_number %d is not enabled",
peripheral_number);
return;
}
switch (protocol_hal_index(lsp))
{
// Request to send eth frame from minidochazka
case HAL_EMAC_INDEX_SEND_FRAME:
{
#if ETH_ENABLE_DEBUG_LOG
logger_fmt("ETH number %d, command %s, size of packet %d",
peripheral_number, hal_index_to_text(peripheral_id, protocol_hal_index(lsp)),
protocol_data_size(lsp));
#endif
//sent data to socket.
ethernet_communication_send(eth_socket,
protocol_data_payload(lsp), protocol_data_size(lsp));
break;
}
}
}
int ethernet_communication_enable_pp(uint8_t peripheral_number,
PERIPHERAL_PHYSICAL_ACTION action)
{
if (ENABLE_PP == action)
{
logger_fmt("ETH number %d, enabled", peripheral_number);
peripheral_psysical_status |= 1U << peripheral_number;
}
else if (DISABLE_PP == action)
{
logger_fmt("ETH number %d, disabled", peripheral_number);
peripheral_psysical_status &= ~(1U << peripheral_number);
}
return 0;
}
_______________________________________________
lwip-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lwip-users