Using BPF/XDP with Mininet - networking

I've created the following network topology in Mininet to run an algorithm I've implemented using the Linux kernel eXpress Data Path.
The objective is to sample packets on the incoming link s1-eth1 on Switch 1 using XDP and store metadata in a shared BPF map. The execution is successful when run on multiple VMs (instead of using Mininet to create an emulation).
However, when using XDP on Mininet (to listen on the emulated network interface), packets aren't recorded.
To further diagnose the cause, I ran Wireshark to listen on the s1-eth1 interface, which does record packets hitting the interface, but for some reason these same packets aren't being registered through the XDP pipeline.
#define KBUILD_MODNAME "foo"
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
//BPF_TABLE("percpu_array", uint32_t, long, dropcnt, 256);
BPF_HASH(proto_map, uint32_t, uint32_t, 256);
//Packet Counter to keep track of number of packets flowing through XDP
BPF_ARRAY(pkt_count, uint64_t, 1);
//Map to keep track of the current EPOCH SIZE
BPF_ARRAY(epoch_size_map, uint64_t, 1);
static inline int parse_ipv4(void *data, u64 nh_off, void *data_end,
__be32 *src, __be32 *dest)
{
struct iphdr *iph = data + nh_off;
if (iph + 1 > data_end)
return 0;
*src = iph->saddr;
*dest = iph->daddr;
return iph->protocol;
}
static inline int bitXor(int* x, int* y)
{
int a = *x & *y;
int b = ~*x & ~*y;
int z = ~a & ~b;
return z;
}
int xdp_dsa(struct CTXTYPE *ctx) {
void* data_end = (void*)(long)ctx->data_end;
void* data = (void*)(long)ctx->data;
struct ethhdr *eth = data;
// drop packets
int rc = RETURNCODE; // let pass XDP_PASS or redirect to tx via XDP_TX
uint32_t *value;
uint32_t *counter_value;
uint32_t *epoch_size;
uint16_t h_proto;
uint64_t nh_off = 0;
uint32_t ipproto;
uint64_t magic_value = 12345678;
uint32_t packet = 0;
__be32 src_ip = 0, dest_ip = 0;
nh_off = sizeof(*eth);
if (data + nh_off > data_end)
pkt_count.increment(packet);
return rc;
h_proto = eth->h_proto;
if (h_proto == htons(ETH_P_IP))
ipproto = parse_ipv4(data, nh_off, data_end, &src_ip, &dest_ip);
/*
else if (h_proto == htons(ETH_P_IPV6))
index = parse_ipv6(data, nh_off, data_end);
*/
else
ipproto = 0; //i.e. unknown protocol
/*XOR the srcIP, destIP, and ipproto to encode, then hash*/
int xor_src_dest = bitXor(&src_ip, &dest_ip);
int xor_srcdst_ipproto = bitXor(&xor_src_dest, &ipproto);
uint32_t zero = 0;
//Predecided initial epoch size
uint32_t init_epoch_size = 10;
//Variable to store the current epoch size (to check end of epoch)
uint32_t cur_epoch_size;
//Lookup epoch size from shared map (to check whether intialized else read)
epoch_size = epoch_size_map.lookup(&zero);
// Start condition (epoch size map is initialized with zero), then set to initial epoch size
// Else read the current epoch size into a variable
if(epoch_size)
{
if(*epoch_size == 0)
{
*epoch_size = init_epoch_size;
}
else
{
cur_epoch_size = *epoch_size;
}
}
counter_value = pkt_count.lookup(&packet);
if (counter_value)
{
if (*counter_value < cur_epoch_size)
{
value = proto_map.lookup_or_init(&xor_srcdst_ipproto, &zero);
if (value)
{
pkt_count.increment(packet);
*value += 1;
}
}
else if (*counter_value == cur_epoch_size)
{
pkt_count.update(&packet, &magic_value);
}
else if(*counter_value == magic_value)
{
return rc;
}
}
return rc;
}
Any ideas?

Related

Having issues when attempting to declare constant variable in arduino

I am making a fairly simple script for sound on my arduino. Here's my script:
#include <digitalWriteFast.h>
struct AudioHandler {
//Alter these as you require
const int pin = 2;
float frequency = 1;
float dutyCycle = 1;
//These are internal variables that you shouldn't touch
unsigned long prevMicros = 0;
bool onHalf = true; //This just asks which half of the wave the sound is on
//This just checks the time and asks if it should switch to the other half of the wave
void updateSound() {
if ((micros() - prevMicros > (1000000 / frequency) * dutyCycle) && (onHalf)) {
prevMicros = micros();
onHalf = false;
digitalWriteFast(pin,false);
} else if ((micros() - prevMicros > (1000000 / frequency) * (1 - dutyCycle)) && (!onHalf)) {
prevMicros = micros();
onHalf = true;
digitalWriteFast(pin,true);
}
}
};
AudioHandler test_1;
AudioHandler test_2;
AudioHandler test_3;
AudioHandler test_4;
void setup() {
pinModeFast(3,OUTPUT); test_1.frequency = 65.41; test_1.dutyCycle = 0.5;
pinModeFast(4,OUTPUT); test_2.frequency = 82.41; test_2.dutyCycle = 0.5;
pinModeFast(5,OUTPUT); test_3.frequency = 98.00; test_3.dutyCycle = 0.5;
pinModeFast(6,OUTPUT); test_4.frequency = 130.81; test_4.dutyCycle = 0.5;
//I need to set the pin, but couldn't figure out how to do it in struct declaration
//Also, this
int *pinPointer_1; pinPointer_1 = &test_1.pin; *pinPointer_1 = 3;
int *pinPointer_2; pinPointer_2 = &test_2.pin; *pinPointer_2 = 4;
int *pinPointer_3; pinPointer_3 = &test_3.pin; *pinPointer_3 = 5;
int *pinPointer_4; pinPointer_4 = &test_4.pin; *pinPointer_4 = 6;
}
void loop() {
test_1.updateSound();
test_2.updateSound();
test_3.updateSound();
test_4.updateSound();
}
Effectively my script SHOULD work fine, but the arduino IDE is complaining:
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB
C:\Users\aj200\Documents\GitHub\My-Projects\My-Projects\Active Projects\Sound_PWM_Help\Sound_PWM_Help.ino: In member function 'updateSound':
Sound_PWM_Help:19:7: error: call to 'NonConstantUsed' declared with attribute error:
digitalWriteFast(pin,false);
^
Sound_PWM_Help:24:7: error: call to 'NonConstantUsed' declared with attribute error:
digitalWriteFast(pin,true);
^
lto-wrapper.exe: fatal error: C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-gcc returned 1 exit status
compilation terminated.
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: error: lto-wrapper failed
collect2.exe: error: ld returned 1 exit status
exit status 1
call to 'NonConstantUsed' declared with attribute error:
In theory, this should be complete and functional. HOWEVER, for some reason the arduino compiler is saying that the variable "pin" is not constant (digitalWriteFast(pin,state) requires constant value annoyingly). What am I missing here?
Thanking you in advance,
Andrey
Why don't you create a struct constructor to assign the pins. Then a setup method could define them as pins using pinModeFast()
This is my take on this. Compiled successfully for Arduino Uno and Leonardo but untested for now. To me, it looks cleaner and easier to follow and grow
#include <digitalWriteFast.h>
struct AudioHandler {
//Alter these as you require
int _pin;
float frequency;
float dutyCycle;
AudioHandler(int pin){
_pin = pin;
}
//These are internal variables that you shouldn't touch
unsigned long prevMicros = 0;
bool onHalf = true; //This just asks which half of the wave the sound is on
//This just checks the time and asks if it should switch to the other half of the wave
void updateSound() {
if ((micros() - prevMicros > (1000000 / frequency) * dutyCycle) && (onHalf)) {
prevMicros = micros();
onHalf = false;
digitalWriteFast(_pin, LOW); // Changed from false
} else if ((micros() - prevMicros > (1000000 / frequency) * (1 - dutyCycle)) && (!onHalf)) {
prevMicros = micros();
onHalf = true;
digitalWriteFast(_pin, HIGH); // Changed from true
}
}
void setup(int freq, int duty){
pinModeFast(_pin, OUTPUT);
frequency = freq;
dutyCycle = duty;
}
};
// Instantiate your audio handlers passing the pin number according to the constructor
AudioHandler test_1 = AudioHandler(3);
AudioHandler test_2 = AudioHandler(4);
AudioHandler test_3 = AudioHandler(5);
AudioHandler test_4 = AudioHandler(6);
void setup() {
// Set them up passing frequency and duty cycle
test_1.setup(65.41,0.5);
test_2.setup(82.41, 0.5);
test_3.setup(98.00, 0.5);
test_4.setup(130.81,0.5);
}
void loop() {
test_1.updateSound();
test_2.updateSound();
test_3.updateSound();
test_4.updateSound();
}

ffmpeg RTSP stream decoding memory leak

I need to decode rtsp stream from Ip camera using ffmpeg, below is the code for decoder
ffmpeg_decoder.h
class ffmpeg_decoder
{
public:
ffmpeg_decoder();
int initial(QString & url);
int h264Decodec();
void close_stream();
virtual ~ffmpeg_decoder();
AVPicture picture;
int width;
int height;
QMutex mutex;
QImage imageDecoded;
private:
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVFrame *pFrame;
AVPacket packet;
SwsContext * pSwsCtx;
int videoStream;
QString rtspURL;
};
ffmpeg_decoder.cpp
ffmpeg_decoder::ffmpeg_decoder()
{
pCodecCtx = NULL;
videoStream=-1;
}
ffmpeg_decoder::~ffmpeg_decoder()
{
sws_freeContext(pSwsCtx);
}
int ffmpeg_decoder::initial(QString & url)
{
int err;
rtspURL=url;
AVCodec *pCodec;
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
pFrame = av_frame_alloc();
err = avformat_open_input(&pFormatCtx, rtspURL.toStdString().c_str(), NULL,
NULL);
if (err < 0)
{
printf("Can not open this file");
return -1;
}
if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
{
printf("Unable to get stream info");
return -1;
}
int i = 0;
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
printf("Unable to find video stream");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
width=pCodecCtx->width;
height=pCodecCtx->height;
avpicture_alloc(&picture,PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
pSwsCtx = sws_getContext(width, height, PIX_FMT_YUV420P, width,
height, PIX_FMT_RGB24,
SWS_BICUBIC, 0, 0, 0);
if (pCodec == NULL)
{
printf("Unsupported codec");
return -1;
}
printf("video size : width=%d height=%d \n", pCodecCtx->width,
pCodecCtx->height);
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Unable to open codec");
return -1;
}
printf("initial successfully");
return 0;
}
int ffmpeg_decoder::h264Decodec()
{
int frameFinished=0;
// while (av_read_frame(pFormatCtx, &packet) >= 0)
if(av_read_frame(pFormatCtx, &packet) >= 0)
{
if(packet.stream_index==videoStream)
{
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished)
{
printf("***************ffmpeg decodec*******************\n");
mutex.lock();
int rs = sws_scale(pSwsCtx, (const uint8_t* const *) pFrame->data,
pFrame->linesize, 0,
height, picture.data, picture.linesize);
imageDecoded = QImage();
imageDecoded= QImage(this->picture.data[0],this->width,this->height,QImage::Format_RGB888);
//imageDecoded = imageDecoded.copy();
mutex.unlock();
if (rs == -1)
{
printf("__________Can open to change to des imag_____________e\n");
return -1;
}
}
}
}
av_free_packet(&packet);
av_frame_unref(pFrame);
av_packet_unref(&packet);
avpicture_free(&picture);
return 1;
}
void ffmpeg_decoder::close_stream(){
/*if (pFrame)
av_free(&pFrame);*/
if (pCodecCtx)
avcodec_close(pCodecCtx);
if (pSwsCtx)
sws_freeContext(pSwsCtx);
avpicture_free(&picture);
if (pFormatCtx)
avformat_close_input(&pFormatCtx);
}
Below is the main thread which do the decoding.
I am using Qt for creating thread and do decoding
ffmpeg_decoder * ffmpeg = new ffmpeg_decoder();;
if(ffmpeg->initial(rtspURL)==0){
while (1) {
ffmpeg->h264Decodec();
//get frame and do processing right now it disabled, and still see the memory leak.
.......
if(stopFlg.load()==1)
break;
}
//close stream if break
ffmpeg->close_stream();
}
else {
ffmpeg->close_stream();
}
When I run 36 thread with different URL I can see the memory usage of the program increase over time.
I have used valgrind to detect the leak, and here is the relevant part of the log
This is the first memory leak location
=14402== by 0x692017F: av_malloc (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x692048D: av_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x691915E: av_frame_alloc (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x419663: ffmpeg_decoder::initial(QString&) (ffmpeg_decoder.cpp:24)
==14402== by 0x41ABEC: RTSP_Player_Object::run() (rtsp_player_object.cpp:15)
Another
==14402== 2,176 bytes in 16 blocks are indirectly lost in loss record 23,113 of 23,379
==14402== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14402== by 0x7780A4E: QImageData::create(unsigned char*, int, int, int, QImage::Format, bool, void (*)(void*), void*) (in /home/vapplica/Qt5.11.1/5.11.1/gcc_64/lib/libQt5Gui.so.5.11.1)
==14402== by 0x7780C30: QImage::QImage(unsigned char*, int, int, QImage::Format, void (*)(void*), void*) (in /home/vapplica/Qt5.11.1/5.11.1/gcc_64/lib/libQt5Gui.so.5.11.1)
==14402== by 0x419B21: ffmpeg_decoder::h264Decodec() (ffmpeg_decoder.cpp:96)
I have check the documentation and sample on ffmpeg site, and I think I am releasing the allocated memory, but still I can see the memory leak when I run the program.

Capturing berr-counter tx/rx from ip link show

I would like to be able to capture the berr-counter values in a shell script. I can view the values with:
ip -det link show can0 which gives:
2: can0: <NOARP,ECHO> mtu 16 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
link/can promiscuity 0
can state STOPPED (berr-counter tx 144 rx 128) restart-ms 100
bitrate 125000 sample-point 0.866
tq 133 prop-seg 6 phase-seg1 6 phase-seg2 2 sjw 1
flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
clock 30000000
I could just parse this output and capture the tx/rx berr-counter, but I would rather capture these values directly. So, I have been trying find where to access these values. I dug into https://github.com/shemminger/iproute2 's code and found where these values are being printed in ip/iplink_can.c in the function:
static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
There is the code:
if (tb[IFLA_CAN_BERR_COUNTER]) {
struct can_berr_counter *bc =
RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
fprintf(f, "(berr-counter tx %d rx %d) ", bc->txerr, bc->rxerr);
}
And at the bottom of the same file there is a struct:
struct link_util can_link_util = {
.id = "can",
.maxattr = IFLA_CAN_MAX,
.parse_opt = can_parse_opt,
.print_opt = can_print_opt,
.print_xstats = can_print_xstats,
.print_help = can_print_help,
};
But I can't find anywhere where can_print_opt, or can_link_util.print_opt are called, and I haven't found any success sifting through all of the struct rtattr in the repo.
I'm not sure where to go from here to get these values other than just grabbing them from the output of ip -det link show can0
Maybe a little bit late, but I was trying the same thing : access CAN interface state and error counters from within a userspace application, without calling ip and parsing output.
As you did, I explored iproute2's code, and then read some documentation about netlink for interacting with network devices. Mainly what you have to do is to send an RTM_GETLINK message to a netlink socket, then parse the response, that is a nested list of netlink attributes.
I found this very interesting starting point : http://iijean.blogspot.com/2010/03/howto-get-list-of-network-interfaces-in.html
In this blog the link to full code is broken, but it's available here : https://gist.github.com/cl4u2/5204374.
Note that instead of doing all this "manually", it is also possible to use libnetlink.
Based on this, I was able to write a test code - quick and dirty - that does what you want. You only need to determine my ifIndex_ variable, which is the integer index of your CAN network interface (can be determined by a SIOCGIFINDEX ioctl on your socketcan socket).
printf("Starting rtnetlink stats reading ...\n");
struct sockaddr_nl local;
struct {
struct nlmsghdr nlh;
struct ifinfomsg ifinfo;
} request;
struct sockaddr_nl kernel;
struct msghdr rtnl_msg;
struct iovec io;
pid_t pid = getpid();
qint64 rtnetlink_socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = pid;
local.nl_groups = 0;
if (bind(rtnetlink_socket, (struct sockaddr *) &local, sizeof(local)) < 0) {
printf("Binding failed !\n");
return true;
}
printf("Binding successful.\n");
memset(&rtnl_msg, 0, sizeof(rtnl_msg));
memset(&kernel, 0, sizeof(kernel));
memset(&request, 0, sizeof(request));
kernel.nl_family = AF_NETLINK;
request.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
request.nlh.nlmsg_type = RTM_GETLINK;
request.nlh.nlmsg_flags = NLM_F_REQUEST; // NLM_F_ROOT|NLM_F_MATCH| were originally specified and return all interfaces.
request.nlh.nlmsg_pid = pid;
request.nlh.nlmsg_seq = 1; // Must be monotonically increasing, but we send only one.
// Interface is specified only with index.
request.ifinfo.ifi_family = AF_PACKET;
request.ifinfo.ifi_index = ifIndex_;
request.ifinfo.ifi_change = 0;
io.iov_base = &request;
io.iov_len = request.nlh.nlmsg_len;
rtnl_msg.msg_iov = &io;
rtnl_msg.msg_iovlen = 1;
rtnl_msg.msg_name = &kernel;
rtnl_msg.msg_namelen = sizeof(kernel);
if (sendmsg(rtnetlink_socket, &rtnl_msg, 0) < 0) {
printf("Sendmsg finished with an error.\n");
return true;
}
printf("Sendmsg finished successfully.\n");
// Reply reception
int end = 0;
int replyMaxSize = 8192;
char reply[replyMaxSize];
while (!end) {
int len;
struct nlmsghdr *msg_ptr;
struct msghdr rtnl_reply;
struct iovec io_reply;
memset(&io_reply, 0, sizeof(io_reply));
memset(&rtnl_reply, 0, sizeof(rtnl_reply));
io.iov_base = reply;
io.iov_len = replyMaxSize;
rtnl_reply.msg_iov = &io;
rtnl_reply.msg_iovlen = 1;
rtnl_reply.msg_name = &kernel;
rtnl_reply.msg_namelen = sizeof(kernel);
printf("Waiting for data ...\n");
len = recvmsg(rtnetlink_socket, &rtnl_reply, 0);
printf("Received data with length %d.\n", len);
if (len) {
for (msg_ptr = (struct nlmsghdr *) reply; NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) {
switch(msg_ptr->nlmsg_type) {
case NLMSG_DONE:
end++;
printf("Received NLMSG_DONE end message.\n");
break;
case RTM_NEWLINK:
printf("Received RTM_NEWLINK message with multipart flag : %d.\n", msg_ptr->nlmsg_flags & NLM_F_MULTI);
if (!(msg_ptr->nlmsg_flags & NLM_F_MULTI)) { end++; }
struct ifinfomsg *iface;
struct rtattr *attribute;
struct rtattr *subAttr;
int msgLen, attrPayloadLen;
iface = (struct ifinfomsg*)NLMSG_DATA(msg_ptr);
msgLen = msg_ptr->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));
for (attribute = IFLA_RTA(iface); RTA_OK(attribute, msgLen); attribute = RTA_NEXT(attribute, msgLen)) {
switch(attribute->rta_type) {
case IFLA_IFNAME:
printf("Interface %d name : %s\n", iface->ifi_index, (char *) RTA_DATA(attribute));
break;
case IFLA_LINKINFO:
attrPayloadLen = RTA_PAYLOAD(attribute);
printf("Found link information. Parsing %d payload bytes ...\n", attrPayloadLen);
for (subAttr = (struct rtattr *)RTA_DATA(attribute); RTA_OK(subAttr, attrPayloadLen); subAttr = RTA_NEXT(subAttr, attrPayloadLen)) {
struct rtattr *subSubAttr;
int subAttrPayloadLen = RTA_PAYLOAD(subAttr);
printf("Found sub-attribute. Type : %d, length : %d.\n", subAttr->rta_type, subAttr->rta_len);
switch (subAttr->rta_type) {
case IFLA_INFO_KIND:
printf("\t Link kind : %s.\n", (char *) RTA_DATA(subAttr));
break;
case IFLA_INFO_DATA:
printf("Found link information data. Parsing %d payload bytes ...\n", RTA_PAYLOAD(subAttr));
for (subSubAttr = (struct rtattr *)RTA_DATA(subAttr); RTA_OK(subSubAttr, subAttrPayloadLen); subSubAttr = RTA_NEXT(subSubAttr, subAttrPayloadLen)) {
printf("Found sub-sub-attribute. Type : %d, length : %d.\n", subSubAttr->rta_type, subSubAttr->rta_len);
switch (subSubAttr->rta_type) {
case IFLA_CAN_STATE:
{
int state = *(int *)RTA_DATA(subSubAttr);
printf("State : %d\n", state);
break;
}
case IFLA_CAN_BERR_COUNTER:
{
struct can_berr_counter *bc = (struct can_berr_counter *)RTA_DATA(subSubAttr);
printf("Error counters : (berr-counter tx %d rx %d)\n", bc->txerr, bc->rxerr);
break;
}
default:
break;
}
}
break;
case IFLA_INFO_XSTATS:
default:
break;
}
}
break;
default:
printf("New attribute. Type : %d, length : %d.\n", attribute->rta_type, attribute->rta_len);
break;
}
}
printf("Finished parsing attributes.\n");
break;
case NLMSG_ERROR:
printf("Could not read link details for interface %d.\n", ifIndex_);
end++;
break;
default:
printf("Received unexpected message ID : %d.\n", msg_ptr->nlmsg_type);
break;
}
printf("Finished parsing message.\n");
}
printf("Finished parsing data.\n");
}
}
close(rtnetlink_socket);
return true;

Crashes and strange behaviour when manipulating strings

My chip just stop doing anything. sometimes it prints good results, sometimes its not, i just cant understand whats wrong with this code( and generally any time you using Strings it happens )
void ParseGetRequest(char* data)
{
String parseGET=data;
String from="GET /";
String to="HTTP";
int ind1 = parseGET.indexOf(from);
int ind2 = parseGET.indexOf(to);
parseGET=parseGET.substring(ind1+from.length(), ind2-1);
strcpy(data, parseGET.c_str () );
}
And calling it with :
void readWifDataAsSever(char* reqData)
{
uint8_t buffer[128] = {0};
uint8_t mux_id;
uint32_t len = wifi.recv(&mux_id, buffer, sizeof(buffer), 100);
char serverData[100]={0};
if (len > 0)
{
for(uint32_t i = 0; i < len; i++)
serverData[i]=(char)buffer[i];
ParseGetRequest( serverData ); ///****** the call
Serial.println(serverData); // prints only part of the values
//here the chip just freeze and stop the main loop
NULL termination !!!!
serverData[len ] = '\0';

How do I read ext2 root directory from mapped memory?

I'm making a Remote Filesystem Server for my university and I'm having some trouble with reading the root directory... Here's the thing:
I've read the root inode (inode 2) and it has consistent data, I mean that, for example, owner user Id field is set at '1000'. Then I proceed to read the contents of the inode data blocks, but when I try to access to the data block in question (the only one that is addressed in the inode i_block array, 240 on my debugging) all bytes are set to '0'. Can anyone help me with this? It's really important. Note: I cannot make it another way than with mapped memory and I'm not opening a real disk, but rather opening a .disk linux file. It has been created with the command-line
mkfs.ext2 -F -r 0 -b 1024 ext2.disk 30000
Here's my code:
#include <linux/ext2_fs.h>
typedef struct s_inode *pinode; /* Pointer to inode struct */
typedef struct s_direct *pdir; /* Pointer to direct struct */
int main(int argv, char *argc[]){
int *data;
pdir root = malloc(sizeof(struct s_direct));
/* Code for mpping .disk file, fetching supernode, and other ext2 data */
/* fsys is a global variable that holds general ext2 system data */
fsys->root = get_inode(2);
data = get_cont(fsys->root);
root = (pdir)getblock(data[0]);
}
pinode get_inode(int idx){
pinode inod;
int grp, offs;
grp = (idx-1)/fsys->superblock->s_inodes_per_group;
offs = (idx-1)%fsys->superblock->s_inodes_per_group;
inod = (pinode)&fsys->diskmap[(fsys->group[grp]->itab)+offs*sizeof(struct s_inode)];
return inod;
}
int *get_cont(pinode inod){
int *cont;
int *idx;
int i=0;
int *block;
idx = malloc(sizeof(int));
cont = malloc(sizeof(int));
while(i < inod->i_blocks && i<13) {
realloc(cont, i*sizeof(int));
cont[i]=inod->i_block[i];
i++;
}
if(i < inod->i_blocks){
*idx=13;
block=(int*)getblock(inod->i_block[*idx]);
fetchcont(block, idx, cont, inod->i_blocks, 0);
}
if(i < inod->i_blocks){
block=(int*)getblock(inod->i_block[*idx]);
fetchcont(block, idx, cont, inod->i_blocks, 1);
}
if(i < inod->i_blocks){
block=(int*)getblock(inod->i_block[*idx]);
fetchcont(block, idx, cont, inod->i_blocks, 2);
}
return cont;
}
int fetchcont(int *block, int *idx, int *cont, int lim, int lvl){
int i=0;
if(lvl == 0){
while((*idx) < lim && i<fsys->bsize){
realloc(cont, (*idx)*sizeof(int));
cont[*idx]=block[i];
(*idx)++;
i++;
}
if(i>=fsys->bsize){
return 1;
}else{
return 0;
}
}else{
lvl--;
while(i<fsys->bsize){
if(!fetchcont((int*)getblock(block[i]), idx, cont, lim, lvl)){
return 0;
}
i++;
}
}
}
void *getblock(int idx){
char *block;
int grp, offs;
grp = (idx-1)/fsys->superblock->s_blocks_per_group;
offs = (idx-1)%fsys->superblock->s_blocks_per_group;
block = &fsys->diskmap[fsys->group[grp]->blocks+offs*fsys->bsize];
return block;
}
Solved the problem. I assumed that block n was the n data block, but the offset included ALL the blocks. I've changed my getblock function to
void *getblock(int idx){
return &fsys->diskmap[fsys->bsize*idx];
}
and worked!

Resources