I got this kind of problem with using uint8_t as array which is passed to my transferring function. At the moment of passing from main function to transfer it changes size to 4 elements. Same thing with array which I create inside my transfer function, even though I manually create another array to send my values with passed length from main function. I understand it is because of data alignment and padding on my processor. Is there any way to solve it? Or I'm printing it wrong.
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(uint8_t))
static const char *device = "/dev/spidev0.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;
static void transfer(int fd, const uint8_t *pass, size_t arsize)
{
int ret,i,k;
printf(" rozmiar tabpass=%d ", arsize);
uint8_t *rx = (uint8_t*) malloc(arsize * sizeof(uint8_t));
//this is where I create rx with arsize lenght
uint8_t *tx = (uint8_t*) malloc(arsize * sizeof(uint8_t));
for (i = 0; i < arsize; i++){
*(rx + i) = 0;
*(tx + i) = *(pass + i);
}
for (k = 0; k < (sizeof (pass) / sizeof (pass[0])); k++) {
printf(" a%X\n ", pass[k]);
//here I check length of passed array
}
for (k = 0; k < (sizeof (tx) / sizeof (tx[0])); k++) {
printf(" b%X\n ", tx[k]);
// I check length of newly created array, should be equal to array size
}
printf(" rozmiar tabtx=%d ", ARRAY_SIZE(tx));
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = arsize,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
.cs_change = 0,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
printf(" rozmiar tabrx=%d ", ARRAY_SIZE(rx));
//here it prints size of array equals 4
for (ret = 0; ret < arsize; ret++) {
if (!(ret % 6))
puts("");
printf("%d. %.2X ", ret, rx[ret]);
}
puts("");
tr.cs_change = 1;
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
fd = open(device, O_RDWR);
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
uint8_t tx1[] = {
0x0, 0x1b, 0xa5
};
transfer(fd, tx1, ARRAY_SIZE(tx1));
uint8_t tx2[] = {
0x0, 0x33, 0x30
};
printf(" %d. ", ARRAY_SIZE(tx2));
transfer(fd, tx2, ARRAY_SIZE(tx2));
uint8_t tx3[] = {
0x0, 0x52, 0x90
};
transfer(fd, tx3, ARRAY_SIZE(tx3));
uint8_t tx4[] = {
0x80, 0x60
};
printf(" %d. ", ARRAY_SIZE(tx4));
transfer(fd, tx4, ARRAY_SIZE(tx4));
close(fd);
return ret;
}
For the sizeof operator to give the actual size of the array, you need to:
Allocate the array statically
Refer to the array within its scope of declaration
For example:
void func()
{
int arr[10];
int total_size = sizeof(arr);
int num_of_elements = sizeof(arr)/sizeof(*arr);
...
}
An example of when the array is not statically allocated:
void func()
{
int* arr = malloc(sizeof(int)*10);
int total_size = sizeof(arr); // will give you the size of 'int*'
...
}
An example of when the array is not within its scope of declaration:
void func(int arr[]) // same as 'int* arr'
{
int total_size = sizeof(arr); // will give you the size of 'int*'
...
}
Related
I'm trying to investigate the relationship between accessing array elements and cache misses. I wrote the following codes.
#include <asm/unistd.h>
#include <linux/perf_event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <inttypes.h>
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags) {
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
int main(int argc, char **argv) {
struct perf_event_attr pe;
long long count;
int fd;
char *chars, c;
uint64_t n = 100000000;
int step = 64;
if (argc > 1) {
step = atoi(argv[1]);
}
chars = malloc(n * sizeof(char));
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = PERF_TYPE_HW_CACHE;
pe.size = sizeof(struct perf_event_attr);
pe.config = PERF_COUNT_HW_CACHE_L1D |
PERF_COUNT_HW_CACHE_OP_READ << 8 |
PERF_COUNT_HW_CACHE_RESULT_MISS << 16;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe.config);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < n; i++) {
chars[i] = 1;
}
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
// Read from memory
for (size_t i = 0; i < n; i += step) {
c = chars[i];
}
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
read(fd, &count, sizeof(long long));
printf("%lld\n", count);
close(fd);
free(chars);
}
It is easy to know that only n/step elements in the array chars are accessed and assigned to c. I think the number of cache misses should be n/step if step is larger than the cache line (64 usually). There is no problem when step is small, i.e.,the printed number of count is about n/step. However, if step is a large number, e.g., 1000000, count is equal to about 2n/step. This has confused me for a long time. Could anyone explain this odd result?
I am trying to create a modbus master slave model. I have written modbus slave using pymodbus and modbus master is using c libmodbus.
Slave is having a bunch of register set and register 0 is having value as
register 0, number of register 2, type hex, value 45565345
register 2, number of register 4, type hex, value 10002
I am using modbus over TCP
Below is the c code
/*
* Copyright © 2008-2014 Stéphane Raimbault <stephane.raimbault#gmail.com>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus.h>
#include "unit-test.h"
const int EXCEPTION_RC = 2;
enum {
TCP,
TCP_PI,
RTU
};
int test_server(modbus_t *ctx, int use_backend);
int send_crafted_request(modbus_t *ctx, int function,
uint8_t *req, int req_size,
uint16_t max_value, uint16_t bytes,
int backend_length, int backend_offset);
int equal_dword(uint16_t *tab_reg, const uint32_t value);
#define BUG_REPORT(_cond, _format, _args ...) \
printf("\nLine %d: assertion error for '%s': " _format "\n", __LINE__, # _cond, ## _args)
#define ASSERT_TRUE(_cond, _format, __args...) { \
if (_cond) { \
printf("OK\n"); \
} else { \
BUG_REPORT(_cond, _format, ## __args); \
goto close; \
} \
};
int equal_dword(uint16_t *tab_reg, const uint32_t value) {
return ((tab_reg[0] == (value >> 16)) && (tab_reg[1] == (value & 0xFFFF)));
}
int main(int argc, char *argv[])
{
const int NB_REPORT_SLAVE_ID = 10;
uint8_t *tab_rp_bits = NULL;
uint16_t *tab_rp_registers = NULL;
uint16_t *tab_rp_registers_bad = NULL;
modbus_t *ctx = NULL;
int i;
uint8_t value;
int nb_points;
int rc;
float real;
uint32_t old_response_to_sec;
uint32_t old_response_to_usec;
uint32_t new_response_to_sec;
uint32_t new_response_to_usec;
uint32_t old_byte_to_sec;
uint32_t old_byte_to_usec;
int use_backend;
int success = FALSE;
int old_slave;
if (argc > 1) {
if (strcmp(argv[1], "tcp") == 0) {
use_backend = TCP;
} else if (strcmp(argv[1], "tcppi") == 0) {
use_backend = TCP_PI;
} else if (strcmp(argv[1], "rtu") == 0) {
use_backend = RTU;
} else {
printf("Usage:\n %s [tcp|tcppi|rtu] - Modbus client for unit testing\n\n", argv[0]);
exit(1);
}
} else {
/* By default */
use_backend = TCP;
}
if (use_backend == TCP) {
ctx = modbus_new_tcp("127.0.0.1", 1520);
} else if (use_backend == TCP_PI) {
ctx = modbus_new_tcp_pi("::1", "1520");
} else {
ctx = modbus_new_rtu("/dev/ttyUSB1", 115200, 'N', 8, 1);
}
if (ctx == NULL) {
fprintf(stderr, "Unable to allocate libmodbus context\n");
return -1;
}
modbus_set_debug(ctx, TRUE);
modbus_set_error_recovery(ctx,
MODBUS_ERROR_RECOVERY_LINK |
MODBUS_ERROR_RECOVERY_PROTOCOL);
if (use_backend == RTU) {
modbus_set_slave(ctx, SERVER_ID);
}
modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
modbus_get_response_timeout(ctx, &new_response_to_sec, &new_response_to_usec);
printf("** UNIT TESTING **\n");
rc = modbus_read_registers(ctx, 0x02,
2, tab_rp_registers);
printf(" value %d" , tab_rp_registers[0]);
modbus_close(ctx);
modbus_free(ctx);
ctx = NULL;
close:
/* Free the memory */
free(tab_rp_bits);
free(tab_rp_registers);
/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);
return (success) ? 0 : -1;
}
/* Send crafted requests to test server resilience
and ensure proper exceptions are returned. */
int test_server(modbus_t *ctx, int use_backend)
{
int rc;
int i;
/* Read requests */
const int READ_RAW_REQ_LEN = 6;
const int slave = (use_backend == RTU) ? SERVER_ID : MODBUS_TCP_SLAVE;
uint8_t read_raw_req[] = {
slave,
/* function, address, 5 values */
MODBUS_FC_READ_HOLDING_REGISTERS,
UT_REGISTERS_ADDRESS >> 8, UT_REGISTERS_ADDRESS & 0xFF,
0x0, 0x05
};
/* Write and read registers request */
const int RW_RAW_REQ_LEN = 13;
uint8_t rw_raw_req[] = {
slave,
/* function, addr to read, nb to read */
MODBUS_FC_WRITE_AND_READ_REGISTERS,
/* Read */
UT_REGISTERS_ADDRESS >> 8, UT_REGISTERS_ADDRESS & 0xFF,
(MODBUS_MAX_WR_READ_REGISTERS + 1) >> 8,
(MODBUS_MAX_WR_READ_REGISTERS + 1) & 0xFF,
/* Write */
0, 0,
0, 1,
/* Write byte count */
1 * 2,
/* One data to write... */
0x12, 0x34
};
const int WRITE_RAW_REQ_LEN = 13;
uint8_t write_raw_req[] = {
slave,
/* function will be set in the loop */
MODBUS_FC_WRITE_MULTIPLE_REGISTERS,
/* Address */
UT_REGISTERS_ADDRESS >> 8, UT_REGISTERS_ADDRESS & 0xFF,
/* 3 values, 6 bytes */
0x00, 0x03, 0x06,
/* Dummy data to write */
0x02, 0x2B, 0x00, 0x01, 0x00, 0x64
};
const int INVALID_FC = 0x42;
const int INVALID_FC_REQ_LEN = 6;
uint8_t invalid_fc_raw_req[] = {
slave, 0x42, 0x00, 0x00, 0x00, 0x00
};
int req_length;
uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
int tab_read_function[] = {
MODBUS_FC_READ_COILS,
MODBUS_FC_READ_DISCRETE_INPUTS,
MODBUS_FC_READ_HOLDING_REGISTERS,
MODBUS_FC_READ_INPUT_REGISTERS
};
int tab_read_nb_max[] = {
MODBUS_MAX_READ_BITS + 1,
MODBUS_MAX_READ_BITS + 1,
MODBUS_MAX_READ_REGISTERS + 1,
MODBUS_MAX_READ_REGISTERS + 1
};
int backend_length;
int backend_offset;
if (use_backend == RTU) {
backend_length = 3;
backend_offset = 1;
} else {
backend_length = 7;
backend_offset = 7;
}
printf("\nTEST RAW REQUESTS:\n");
uint32_t old_response_to_sec;
uint32_t old_response_to_usec;
/* This requests can generate flushes server side so we need a higher
* response timeout than the server. The server uses the defined response
* timeout to sleep before flushing.
* The old timeouts are restored at the end.
*/
modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
modbus_set_response_timeout(ctx, 0, 600000);
req_length = modbus_send_raw_request(ctx, read_raw_req, READ_RAW_REQ_LEN);
printf("* modbus_send_raw_request: ");
ASSERT_TRUE(req_length == (backend_length + 5), "FAILED (%d)\n", req_length);
printf("* modbus_receive_confirmation: ");
rc = modbus_receive_confirmation(ctx, rsp);
ASSERT_TRUE(rc == (backend_length + 12), "FAILED (%d)\n", rc);
/* Try to read more values than a response could hold for all data
types. */
for (i=0; i<4; i++) {
rc = send_crafted_request(ctx, tab_read_function[i],
read_raw_req, READ_RAW_REQ_LEN,
tab_read_nb_max[i], 0,
backend_length, backend_offset);
if (rc == -1)
goto close;
}
/* Modbus write and read multiple registers */
rc = send_crafted_request(ctx, MODBUS_FC_WRITE_AND_READ_REGISTERS,
rw_raw_req, RW_RAW_REQ_LEN,
MODBUS_MAX_WR_READ_REGISTERS + 1, 0,
backend_length, backend_offset);
if (rc == -1)
goto close;
/* Modbus write multiple registers with large number of values but a set a
small number of bytes in requests (not nb * 2 as usual). */
rc = send_crafted_request(ctx, MODBUS_FC_WRITE_MULTIPLE_REGISTERS,
write_raw_req, WRITE_RAW_REQ_LEN,
MODBUS_MAX_WRITE_REGISTERS + 1, 6,
backend_length, backend_offset);
if (rc == -1)
goto close;
rc = send_crafted_request(ctx, MODBUS_FC_WRITE_MULTIPLE_COILS,
write_raw_req, WRITE_RAW_REQ_LEN,
MODBUS_MAX_WRITE_BITS + 1, 6,
backend_length, backend_offset);
if (rc == -1)
goto close;
/* Test invalid function code */
modbus_send_raw_request(ctx, invalid_fc_raw_req, INVALID_FC_REQ_LEN * sizeof(uint8_t));
rc = modbus_receive_confirmation(ctx, rsp);
printf("Return an exception on unknown function code: ");
ASSERT_TRUE(rc == (backend_length + EXCEPTION_RC) &&
rsp[backend_offset] == (0x80 + INVALID_FC), "")
modbus_set_response_timeout(ctx, old_response_to_sec, old_response_to_usec);
return 0;
close:
modbus_set_response_timeout(ctx, old_response_to_sec, old_response_to_usec);
return -1;
}
int send_crafted_request(modbus_t *ctx, int function,
uint8_t *req, int req_len,
uint16_t max_value, uint16_t bytes,
int backend_length, int backend_offset)
{
uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
int j;
for (j=0; j<2; j++) {
int rc;
req[1] = function;
if (j == 0) {
/* Try to read or write zero values on first iteration */
req[4] = 0x00;
req[5] = 0x00;
if (bytes) {
/* Write query */
req[6] = 0x00;
}
} else {
/* Try to read or write max values + 1 on second iteration */
req[4] = (max_value >> 8) & 0xFF;
req[5] = max_value & 0xFF;
if (bytes) {
/* Write query (nb values * 2 to convert in bytes for registers) */
req[6] = bytes;
}
}
modbus_send_raw_request(ctx, req, req_len * sizeof(uint8_t));
if (j == 0) {
printf("* try function 0x%X: %s 0 values: ", function, bytes ? "write": "read");
} else {
printf("* try function 0x%X: %s %d values: ", function, bytes ? "write": "read",
max_value);
}
rc = modbus_receive_confirmation(ctx, rsp);
ASSERT_TRUE(rc == (backend_length + EXCEPTION_RC) &&
rsp[backend_offset] == (0x80 + function) &&
rsp[backend_offset + 1] == MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, "");
}
return 0;
close:
return -1;
}
I am getting below output from modbus master
Connecting to 127.0.0.1:1520
** UNIT TESTING **
[00][01][00][00][00][06][FF][03][00][02][00][02]
Waiting for a confirmation...
<00><01><00><00><00><07><FF><03><04><00><01><00><02>
Segmentation fault (core dumped)
Output on modbus slave
DEBUG:pymodbus.server.async:Client Connected [IPv4Address(type='TCP', host='127.0.0.1', port=1520)]
DEBUG:pymodbus.server.async:Data Received: 0x0 0x1 0x0 0x0 0x0 0x6 0xff 0x3 0x0 0x2 0x0 0x2
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x1 0x0 0x0 0x0 0x6 0xff 0x3 0x0 0x2 0x0 0x2
DEBUG:pymodbus.factory:Factory Request[3]
DEBUG:pymodbus.datastore.context:validate[3] 3:2
DEBUG:pymodbus.datastore.context:getValues[3] 3:2
DEBUG:pymodbus.datastore.context:xxxxxxxxxxxxxxxxxxxxxxxxx
DEBUG:pymodbus.datastore.context:[1, 2]
DEBUG:pymodbus.server.async:send: 000100000007ff030400010002
DEBUG:pymodbus.server.async:Client Disconnected: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
I am trying to retrieve value of the register. Not sure why I am not getting the value
I have never used this stack but RTFM says:
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
...
You must take care to allocate enough memory to store the results in dest (at least nb * sizeof(uint16_t)).
But tab_rp_registers is set to NULL and never allocated.
I am new to DPDK and trying to create a packet to send it from one DPDK enabled machine to another connected directly via an ethernet. I modified an example/rxtx_callbacks/main.c provided with DPDK at both side. However, I am not receiving anything at the receiver. What wrong am I doing?
Modified function at transmitter: lcore_main is modified:
static __attribute__((noreturn)) void lcore_main()
{
uint16_t port;
struct ether_hdr *eth_hdr;
struct ether_addr daddr;
daddr.addr_bytes[0] = 116;
daddr.addr_bytes[1] = 225;
daddr.addr_bytes[2] = 228;
daddr.addr_bytes[3] = 204;
daddr.addr_bytes[4] = 106;
daddr.addr_bytes[5] = 82;
//rte_eth_macaddr_get(portid, &addr);
struct ipv4_hdr *ipv4_hdr;
int32_t i;
int ret;
RTE_ETH_FOREACH_DEV(port)
if (rte_eth_dev_socket_id(port) > 0 &&
rte_eth_dev_socket_id(port) !=
(int)rte_socket_id())
printf("WARNING, port %u is on remote NUMA node to "
"polling thread.\n\tPerformance will "
"not be optimal.\n", port);
printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
rte_lcore_id());
//struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
struct rte_mbuf *m_head[BURST_SIZE];
for (;;) {
RTE_ETH_FOREACH_DEV(port) {
if(rte_pktmbuf_alloc_bulk(mbuf_pool, m_head, BURST_SIZE)!=0)
{
printf("Allocation problem\n");
}
for(i = 0; i < BURST_SIZE; i++) {
eth_hdr = rte_pktmbuf_mtod(m_head[i], struct ether_hdr *);
//eth_hdr = (struct ether_hdr *)rte_pktmbuf_append(m_head[i],
// sizeof(struct ether_hdr));
eth_hdr->ether_type = htons(ETHER_TYPE_IPv4);
rte_memcpy(&(eth_hdr->s_addr), &addr, sizeof(struct ether_addr));
rte_memcpy(&(eth_hdr->d_addr), &daddr, sizeof(struct ether_addr));
}
const uint16_t nb_tx = rte_eth_tx_burst(port, 0, m_head, BURST_SIZE);
if (unlikely(nb_tx < BURST_SIZE)) {
uint16_t buf;
for (buf = nb_tx; buf < BURST_SIZE; buf++)
rte_pktmbuf_free(m_head[buf]);
}
}
}
}
receiver side RTE_ETH_FOREACH_DEV of tx part is modified to:
RTE_ETH_FOREACH_DEV(port) {
struct rte_mbuf *bufs[BURST_SIZE];
const uint16_t nb_rx = rte_eth_rx_burst(port, bufs, BURST_SIZE);
//printf("Number of Packets received %d\n", nb_rx);
for(i = 0; i < nb_rx; i++) {
//ipv4_hdr = rte_pktmbuf_mtod_offset(bufs[i], struct ipv4_hdr *,
// sizeof(struct ether_hdr));
//printf("Packet ip received %d\n", ipv4_hdr->src_addr);
eth_hdr = rte_pktmbuf_mtod(bufs[i], struct ether_hdr *);
printf("Packet ip received %d\n", eth_hdr->ether_type);
}
if (unlikely(nb_rx == 0))
continue;
const uint16_t nb_tx = 0; // = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx);
if (unlikely(nb_tx < nb_rx)) {
uint16_t buf;
for (buf = nb_tx; buf < nb_rx; buf++)
rte_pktmbuf_free(bufs[buf]);
}
}
Please let me know if I missed something.
There are few issues with the code:
eth_hdr = rte_pktmbuf_mtod(m_head[i], struct ether_hdr *);
Unlike rte_pktmbuf_append(), the rte_pktmbuf_mtod() does not change the packet length, so it should be set manually before the tx.
eth_hdr->ether_type = htons(ETHER_TYPE_IPv4);
If we set ETHER_TYPE_IPv4, a correct IPv4 header must follow. So we need either to add the header or to change the ether_type.
rte_memcpy(&(eth_hdr->s_addr), &addr, sizeof(struct ether_addr));
Where is the source address comes from?
const uint16_t nb_tx = rte_eth_tx_burst(port, 0, m_head, BURST_SIZE);
Looks like we transmit a burst of zero-sized packets with invalid IPv4 headers. Please also make sure the source/destination addresses are correct.
As suggested by #andriy-berestovsky, I used rte_eth_stats_get() and it shows packets are present in ethernet ring via the field ipackets but rte_eth_rx_burst is not returning any packets. Full code is included here, please let me know what I am doing wrong. (I am using testpmd at transmitter side)
#include <stdint.h>
#include <inttypes.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_cycles.h>
#include <rte_lcore.h>
#include <rte_ip.h>
#include <rte_mbuf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <signal.h>
#define MAX_SOURCE_SIZE (0x100000)
#define RX_RING_SIZE 1024
#define TX_RING_SIZE 1024
#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32
static const struct rte_eth_conf port_conf_default = {
.rxmode = {
.max_rx_pkt_len = ETHER_MAX_LEN,
},
};
static struct {
uint64_t total_cycles;
uint64_t total_pkts;
} latency_numbers;
static volatile bool force_quit;
struct rte_mempool *mbuf_pool;
static void
signal_handler(int signum)
{
struct rte_eth_stats eth_stats;
int i;
if (signum == SIGINT || signum == SIGTERM) {
printf("\n\nSignal %d received, preparing to exit...\n",
signum);
RTE_ETH_FOREACH_DEV(i) {
rte_eth_stats_get(i, ð_stats);
printf("Total number of packets received %llu, dropped rx full %llu and rest= %llu, %llu, %llu\n", eth_stats.ipackets, eth_stats.imissed, eth_stats.ierrors, eth_stats.rx_nombuf, eth_stats.q_ipackets[0]);
}
force_quit = true;
}
}
struct ether_addr addr;
/*
* Initialises a given port using global settings and with the rx buffers
* coming from the mbuf_pool passed as parameter
*/
static inline int
port_init(uint16_t port, struct rte_mempool *mbuf_pool)
{
struct rte_eth_conf port_conf = port_conf_default;
const uint16_t rx_rings = 1, tx_rings = 1;
uint16_t nb_rxd = RX_RING_SIZE;
uint16_t nb_txd = TX_RING_SIZE;
int retval;
uint16_t q;
struct rte_eth_dev_info dev_info;
struct rte_eth_txconf txconf;
if (!rte_eth_dev_is_valid_port(port))
return -1;
rte_eth_dev_info_get(port, &dev_info);
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
port_conf.txmode.offloads |=
DEV_TX_OFFLOAD_MBUF_FAST_FREE;
retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
if (retval != 0)
return retval;
retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
if (retval != 0) {
printf("Error in adjustment\n");
return retval;
}
for (q = 0; q < rx_rings; q++) {
retval = rte_eth_rx_queue_setup(port, q, nb_rxd,
rte_eth_dev_socket_id(port), NULL, mbuf_pool);
if (retval < 0) {
printf("RX queue setup prob\n");
return retval;
}
}
txconf = dev_info.default_txconf;
txconf.offloads = port_conf.txmode.offloads;
for (q = 0; q < tx_rings; q++) {
retval = rte_eth_tx_queue_setup(port, q, nb_txd,
rte_eth_dev_socket_id(port), &txconf);
if (retval < 0)
return retval;
}
retval = rte_eth_dev_start(port);
if (retval < 0) {
printf("Error in start\n");
return retval;
}
rte_eth_macaddr_get(port, &addr);
printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
(unsigned)port,
addr.addr_bytes[0], addr.addr_bytes[1],
addr.addr_bytes[2], addr.addr_bytes[3],
addr.addr_bytes[4], addr.addr_bytes[5]);
rte_eth_promiscuous_enable(port);
return 0;
}
/*
* Main thread that does the work, reading from INPUT_PORT
* and writing to OUTPUT_PORT
*/
static __attribute__((noreturn)) void
lcore_main(void)
{
uint16_t port;
struct ether_hdr *eth_hdr;
//struct ether_addr addr;
//rte_eth_macaddr_get(portid, &addr);
struct ipv4_hdr *ipv4_hdr;
int32_t i;
RTE_ETH_FOREACH_DEV(port)
{
if (rte_eth_dev_socket_id(port) > 0 &&
rte_eth_dev_socket_id(port) !=
(int)rte_socket_id())
printf("WARNING, port %u is on remote NUMA node to "
"polling thread.\n\tPerformance will "
"not be optimal.\n", port);
}
printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
rte_lcore_id());
for (;;) {
RTE_ETH_FOREACH_DEV(port) {
struct rte_mbuf *bufs[BURST_SIZE];
const uint16_t nb_rx = rte_eth_rx_burst(port, 0,bufs, BURST_SIZE);
for(i = 0; i < nb_rx; i++) {
ipv4_hdr = rte_pktmbuf_mtod_offset(bufs[i], struct ipv4_hdr *, sizeof(struct ether_hdr));
printf("Packet ip received %d\n", ipv4_hdr->src_addr);
}
if (unlikely(nb_rx == 0))
continue;
const uint16_t nb_tx = 0; // = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx);
if (unlikely(nb_tx < nb_rx)) {
uint16_t buf;
for (buf = nb_tx; buf < nb_rx; buf++)
rte_pktmbuf_free(bufs[buf]);
}
}
if(force_quit)
break;
}
}
/* Main function, does initialisation and calls the per-lcore functions */
int
main(int argc, char *argv[])
{
uint16_t nb_ports;
uint16_t portid, port;
/* init EAL */
int ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
argc -= ret;
argv += ret;
force_quit = false;
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
nb_ports = rte_eth_dev_count_avail();
printf("size ordered %lld\n", NUM_MBUFS *nb_ports);
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL",
NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0,
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if (nb_ports < 1)
rte_exit(EXIT_FAILURE, "Error: number of ports must be greater than %d\n", nb_ports);
if (mbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
// initialize all ports
RTE_ETH_FOREACH_DEV(portid)
if (port_init(portid, mbuf_pool) != 0)
rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n",
portid);
if (rte_lcore_count() > 1)
printf("\nWARNING: Too much enabled lcores - "
"App uses only 1 lcore\n");
// call lcore_main on master core only
lcore_main();
return 0;
}
It seems to be a problem of ethernet card with ubuntu 14.04. With ubuntu 16.04 it is working fine.
I wrote a C program on the Beaglebone Black to read and write to the 25LC256 (EEPROM). I am able to compile it without any errors or warnings, gcc SPI.c -o SPI, but when I try running it ./SPI, my entire Beaglebone stops working, and I have to reboot it. In fact, the program doesn't even output anything. I have the code print out "Starting" at the begging, but that doesn't even work.
Could anybody see where I might be going wrong ?
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
//You need to correctly identify the SPI device bus and number
int write64NVM(int fd, unsigned char data[], int length, unsigned int add);
int read64NVM(int fd, unsigned char to[], int length, unsigned int add);
static const char *device = "/dev/spidev1.0";
int main(){
uint8_t mode=0, bits=8;
uint32_t speed=500000;
int file;
printf("Starting");
if ((file = open(device, O_RDWR))<0){
perror("SPI: Can't open device.");
return -1;
}
if (ioctl(file, SPI_IOC_WR_MODE, &mode)==-1){
perror("SPI: Can't set SPI mode.");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MODE, &mode)==-1){
perror("SPI: Can't get SPI mode.");
return -1;
}
if (ioctl(file, SPI_IOC_WR_BITS_PER_WORD, &bits)==-1){
perror("SPI: Can't set bits per word.");
return -1;
}
if (ioctl(file, SPI_IOC_RD_BITS_PER_WORD, &bits)==-1){
perror("SPI: Can't get bits per word.");
return -1;
}
if(ioctl(file, SPI_IOC_WR_MAX_SPEED_HZ, &speed)==-1){
perror("SPI: Can't set max speed HZ");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MAX_SPEED_HZ, &speed)==-1){
perror("SPI: Can't get max speed HZ.");
return -1;
}
printf("spi mode: 0x%xn", mode);
printf("bits per word: %dn", bits);
printf("max speed: %d Hz (%d KHz)n", speed, speed/1000);
// sending one byte on the MOSI line and receiving the data on MISO
write64NVM(file, "hello", 6, 0);
close(file);
return 0;
}
int write64NVM(int fd, unsigned char data[], int length, unsigned int add)
{
unsigned char InstructionBuffer[1], AddressBuffer[3];
int status;
//DataBuffer = (char *) malloc(length);
struct spi_ioc_transfer xfer[3];
InstructionBuffer[0] = 6; //Set the write enable latch (enable write operations)
AddressBuffer[0] = 2; //Write data to memory array beginning at selected address
AddressBuffer[1] = (add >> 8);
AddressBuffer[2] = (add & 0b11111111);
//DataBuffer = data;
//First Transaction
xfer[0].tx_buf = (unsigned long)InstructionBuffer;
xfer[0].rx_buf = (unsigned long)NULL;
xfer[0].len = 1;
xfer[0].cs_change = 1;
//Second transaction
xfer[1].tx_buf = (unsigned long)AddressBuffer;
xfer[1].rx_buf = (unsigned long)NULL;
xfer[1].len = 3;
xfer[1].cs_change = 0;
//Third transaction
xfer[2].tx_buf = (unsigned long)data;
xfer[2].rx_buf = (unsigned long)NULL;
xfer[2].len = length;
xfer[2].cs_change = 1;
status = ioctl(fd, SPI_IOC_MESSAGE(3), &xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE error");
return;
}
return status;
}
int read64NVM(int fd, unsigned char to[], int length, unsigned int add){
//Read Sequence :
//Pull ~CS low
//The 8-bit instruction is transmited to EEPROM followed
//by 16-bit address, with first MSB of the address being a 'dont care'
//bit.
//According to Page 7 Figure 2-1 of the 25LC256.pdf, to read an address from
//EEPROM, the BBB must only send out 2 transactions. The instruction and the address.
//In this case, the instruction is read, so the value of transaction is 3.
//~CS apears to be kept low throughout the entire transaction until data
//has completely been shifted out of EEPROM.
//Like in write64NVM, there are 3 buffers
//unsigned char InstructionBuffer, AddressBuffer[3], DataBuffer[8],
//but the latter will be used to store the Data recieved.
unsigned char InstructionBuffer, AddressBuffer[2], *DataBuffer;
int status;
//DataBuffer = (char *) malloc(length);
struct spi_ioc_transfer xfer[3];
InstructionBuffer = 3; //Read intruction value
//AddressBuffer[0] = 2;
AddressBuffer[0] = add >> 8;
AddressBuffer[1] = add & 0b11111111;
DataBuffer = 0;
//First Transaction
xfer[0].tx_buf = (unsigned long)&InstructionBuffer;
xfer[0].rx_buf = (unsigned long)NULL;
xfer[0].len = 1;
xfer[0].cs_change = 1;
//Second transaction
xfer[1].tx_buf = (unsigned long)AddressBuffer;
xfer[1].rx_buf = (unsigned long)NULL;
xfer[1].len = 2;
xfer[1].cs_change = 0;
//Third transaction
xfer[2].tx_buf = (unsigned long)NULL;
xfer[2].rx_buf = (unsigned long)to;
xfer[2].len = length;
xfer[2].cs_change = 1;
status = ioctl(fd, SPI_IOC_MESSAGE(3), &xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE error");
return;
}
return status;
}
Please forgive my poor coding, I'm still a beginner.
I am trying to print a partition table using C programming language, everything seems to work fine: Opening and reading, but I don't understand why it is printing garbage values.
Here is the code:
struct partition
{
unsigned char drive;
unsigned char chs_begin[3];
unsigned char sys_type;
unsigned char chs_end[3];
unsigned char start_sector[4];
unsigned char nr_sector[4];
};
int main()
{
int gc = 0, i = 1, nr = 0, pos = -1, nw = 0;
int fd =0;
char buf[512] ;
struct partition *sp;
printf("Ok ");
if ( (fd = open("/dev/sda", O_RDONLY | O_SYNC )) == -1)
{
perror("Open");
exit(1);
}
printf("fd is %d \n", fd);
pos = lseek (fd, 0, SEEK_CUR);
printf("Position of pointer is :%d\n", pos);
if ((nr = read(fd, buf, sizeof(buf))) == -1)
{
perror("Read");
exit(1);
}
close(fd);
printf("Size of buf = %d\n and number of bytes read are %d ", sizeof(buf), nr);
if ((nw = write(1, buf, 64)) == -1)
{
printf("Write: Error");
exit(1);
}
printf("\n\n %d bytes are just been written on stdout\n", nw,"this can also be printed\n");
printf("\n\t\t*************Partition Table****************\n\n");
for (i=0 ; i<4 ; i++)
{
sp = (struct partition *)(buf + 446 + (16 * i));
putchar(sp -> drive);
}
return 0;
}
It is printing garbage instead of partition table.
I might have some basic understanding issues but I searched with Google for a long time but it did not really help. I also saw the source code of fdisk but it is beyond my understanding at this point. Could anyone please guide me? I am not expecting someone to clear my mistake and give me the working code. Just a sentence or two - or any link.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct partition
{
unsigned char boot_flag; /* 0 = Not active, 0x80 = Active */
unsigned char chs_begin[3];
unsigned char sys_type; /* For example : 82 --> Linux swap, 83 --> Linux native partition, ... */
unsigned char chs_end[3];
unsigned char start_sector[4];
unsigned char nr_sector[4];
};
void string_in_hex(void *in_string, int in_string_size);
void dump_partition(struct partition *part, int partition_number);
void dump_partition(struct partition *part, int partition_number)
{
printf("Partition /dev/sda%d\n", partition_number + 1);
printf("boot_flag = %02X\n", part->boot_flag);
printf("chs_begin = ");
string_in_hex(part->chs_begin, 3);
printf("sys_type = %02X\n", part->sys_type);
printf("chs_end = ");
string_in_hex(part->chs_end, 3);
printf("start_sector = ");
string_in_hex(part->start_sector, 4);
printf("nr_sector = ");
string_in_hex(part->nr_sector, 4);
}
void string_in_hex(void *in_string, int in_string_size)
{
int i;
int k = 0;
for (i = 0; i < in_string_size; i++)
{
printf("%02x ", ((char *)in_string)[i]& 0xFF);
k = k + 1;
if (k == 16)
{
printf("\n");
k = 0;
}
}
printf("\n");
}
int main(int argc, char **argv)
{
int /*gc = 0,*/ i = 1, nr = 0, pos = -1/*, nw = 0*/;
int fd = 0;
char buf[512] ;
struct partition *sp;
int ret = 0;
printf("Ok ");
if ((fd = open("/dev/sda", O_RDONLY | O_SYNC)) == -1)
{
perror("Open");
exit(1);
}
printf("fd is %d\n", fd);
pos = lseek (fd, 0, SEEK_CUR);
printf("Position of pointer is :%d\n", pos);
if ((nr = read(fd, buf, sizeof(buf))) == -1)
{
perror("Read");
exit(1);
}
ret = close(fd);
if (ret == -1)
{
perror("close");
exit(1);
}
/* Dump the MBR buffer, you can compare it on your system with the output of the command:
* hexdump -n 512 -C /dev/sda
*/
string_in_hex(buf, 512);
printf("Size of buf = %d - and number of bytes read are %d\n", sizeof(buf), nr);
/*if ((nw = write(1, buf, 64)) == -1)
{
printf("Write: Error");
exit(1);
}
printf("\n\n%d bytes are just been written on stdout\nthis can also be printed\n", nw);
*/
//printf("\n\t\t*************Partition Table****************\n\n");
printf("\n\t\t*************THE 4 MAIN PARTITIONS****************\n\n");
/* Dump main partitions (4 partitions) */
/* Note : the 4 partitions you are trying to dump are not necessarily existing! */
for (i = 0 ; i < 4 ; i++)
{
sp = (struct partition *)(buf + 446 + (16 * i));
//putchar(sp->boot_flag);
dump_partition(sp, i);
}
return 0;
}