* apps/testing/drivers/enet/util/enet_util.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
* Included Files
****************************************************************************/
#include "enet_util.h"
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
* Pre-processor Definitions
****************************************************************************/
#define DATA_SIZE 200
#define ETH_PTP_TYPE 0x88f7
* Public Functions
****************************************************************************/
* Name: enet_test_setup
****************************************************************************/
int enet_test_setup(void **state)
{
struct senet_testsuites_params *enet_p;
int ret;
enet_p = zalloc(sizeof(struct senet_testsuites_params));
assert_true(enet_p != NULL);
enet_p->enet_dev.if_name = strdup(CONFIG_ENET_TEST_DEV);
*state = enet_p;
ret = netlib_ifup(enet_p->enet_dev.if_name);
assert_true(ret == 0);
enet_p->enet_dev.fd = enet_test_init(enet_p->enet_dev.if_name);
assert_true(enet_p->enet_dev.fd > 0);
return 0;
}
* Private Functions
****************************************************************************/
* Name: enet_test_init
****************************************************************************/
int enet_test_init(const char *enetif)
{
int ret;
int pkt_fd;
struct sockaddr_ll sll;
struct timeval timeout;
struct ifreq ifr;
int ifindex;
int optval;
pkt_fd = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, HTONS(ETH_PTP_TYPE));
assert_true(pkt_fd > 0);
memset(&sll, 0, sizeof(struct sockaddr_ll));
timeout.tv_sec = 0;
timeout.tv_usec = 1;
ret = setsockopt(pkt_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
sizeof(timeout));
assert_true(ret == 0);
ret = setsockopt(pkt_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout,
sizeof(timeout));
assert_true(ret == 0);
optval = 1;
ret = setsockopt(pkt_fd, SOL_SOCKET, SO_DONTROUTE, &optval,
sizeof(optval));
assert_true(ret == 0);
strlcpy(ifr.ifr_name, enetif, IFNAMSIZ);
ret = ioctl(pkt_fd, SIOCGIFINDEX, &ifr);
assert_true(ret == 0);
ifindex = ifr.ifr_ifindex;
ret = ioctl(pkt_fd, SIOCGIFFLAGS, &ifr);
assert_true(ret == 0);
ifr.ifr_flags |= IFF_BROADCAST;
ret = ioctl(pkt_fd, SIOCSIFFLAGS, &ifr);
assert_true(ret == 0);
sll.sll_family = AF_PACKET;
sll.sll_protocol = HTONS(ETH_PTP_TYPE);
sll.sll_ifindex = ifindex;
ret = bind(pkt_fd, (struct sockaddr *)&sll,
sizeof(struct sockaddr_ll));
assert_true(ret == 0);
return pkt_fd;
errout_with_socket:
close(pkt_fd);
return -1;
}
* Name: enet_loop_send_frame
* Description:
* Test sending ethernet frames in a loop (20 times)
****************************************************************************/
void enet_loop_send_frame(void **state)
{
struct senet_testsuites_params *enet_if = *state;
uint8_t data[DATA_SIZE];
const char *message = "Hello, World!";
uint16_t ip_checksum;
int ret;
size_t message_len;
int i;
const int LOOP_COUNT = 20;
memset(data, 0, DATA_SIZE);
data[0] = 0x01; data[1] = 0x00; data[2] = 0x5e;
data[3] = 0x00; data[4] = 0x00; data[5] = 0x00;
data[6] = 0x58; data[7] = 0x32; data[8] = 0x31;
data[9] = 0x32; data[10] = 0x39; data[11] = 0x37;
data[12] = 0x88; data[13] = 0xf7;
data[14] = 0x45;
data[15] = 0x00;
data[16] = 0x00; data[17] = 0x4e;
data[18] = 0x00; data[19] = 0x00;
data[20] = 0x00; data[21] = 0x00;
data[22] = 0x40;
data[23] = 0x11;
data[24] = 0x00; data[25] = 0x00;
data[26] = 0x0a; data[27] = 0x00;
data[28] = 0x00; data[29] = 0x02;
data[30] = 0xff; data[31] = 0xff;
data[32] = 0xff; data[33] = 0xff;
message_len = strlen(message);
memcpy(data + 42, message, message_len);
ip_checksum = 0;
for (int i = 14; i < 34; i += 2)
{
ip_checksum += (data[i] << 8) | data[i + 1];
}
if (ip_checksum >> 16)
{
ip_checksum = (ip_checksum & 0xffff) + (ip_checksum >> 16);
}
ip_checksum = ~ip_checksum;
data[24] = (ip_checksum >> 8) & 0xff;
data[25] = ip_checksum & 0xff;
for (i = 0; i < LOOP_COUNT; i++)
{
ret = send(enet_if->enet_dev.fd, data, DATA_SIZE, 0);
assert_true(ret > 0);
usleep(100000);
}
assert_true(i == LOOP_COUNT);
}
* Name: enet_test_teardown
****************************************************************************/
int enet_test_teardown(void **state)
{
int ret;
struct senet_testsuites_params *enet_p;
if (state == NULL || *state == NULL)
{
return -1;
}
enet_p = *state;
ret = close(enet_p->enet_dev.fd);
assert_true(ret == 0);
ret = netlib_ifdown(enet_p->enet_dev.if_name);
assert_true(ret >= 0);
free(enet_p->enet_dev.if_name);
free(enet_p);
*state = NULL;
return 0;
}