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

Reply via email to