Data appearing as Ethernet Trailer in self made SKB - network-programming

Im trying to make a custom skb in a linux kernel module and then send it over the network.
I succeed in making a SKB but when I send it over the network it does not reach the destination.
If I run wireshark on the local machine that is sending my SBK over the network, it shows my packet. However if I examine the contents of my packet, it shows that the data is being placed as 'Ethernet Trailer'
Also, if I remove all data from my SKB and only send a Header-only SKB, it still does not reach its destination
Here is the code:
u_int32_t local_ip;
u_int32_t remote_ip;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
unsigned short udp_len;
char remote_mac[6];
char local_mac[6];
Allocate a skb:
int header_len = sizeof(*iph) + sizeof(*udph) + sizeof(*eth);
skb = sock_wmalloc(sock->sk, /*payload len*/ len + header_len + LL_RESERVED_SPACE(pfr->ring_netdev->dev), 0, GFP_KERNEL);
Since I am using skb_push, I move down data and tail all the way down:
skb_reserve(skb,
len + header_len + LL_RESERVED_SPACE(pfr->ring_netdev->dev));
Push UDP header:
skb_push(skb, sizeof(*udph));
Reset the transport_pointer accordingly:
skb_reset_transport_header(skb);
Set and populate udp header:
udph = udp_hdr(skb);
udph->source = htons(5123);
udph->dest = htons(5123);
udp_len = 14;
udph->len = htons(udp_len);
udph->check = 0;
local_ip = htonl(0xCB873F2A); /*203.135.63.42*/
remote_ip = htonl(0xCB873F29); /*203.135.61.41*/
udph->check = csum_tcpudp_magic(local_ip,
remote_ip,
udp_len, IPPROTO_UDP,
csum_partial(udph, udp_len, 0));
if (udph->check == 0) {
printk("mangled checksum\n");
udph->check = CSUM_MANGLED_0;
}
Now to push IP header:
skb_push(skb, sizeof(*iph));
Reset the network_pointer:
skb_reset_network_header(skb);
Set and populate the network header:
iph = ip_hdr(skb);
put_unaligned(0x45, (unsigned char *)iph);
iph->tos = 0;
ip_len = 40;
put_unaligned(htons(ip_len), &(iph->tot_len));
//iph->id = htons(atomic_inc_return(&ip_ident));
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;
iph->check = 0;
put_unaligned(local_ip /*"\xC0\xA8\x00\x01"*/, &(iph->saddr));
put_unaligned(remote_ip /*"\xC0\xA8\x00\x01"*/, &(iph->daddr));
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
Push the Ethernet Header:
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
Reset the mac_pointer accordingly:
skb_reset_mac_header(skb);
set and populate the mac_header:
skb->protocol = eth->h_proto = htons(ETH_P_IP);
remote_mac[0] = 0x4C;
remote_mac[1] = 0x72;
remote_mac[2] = 0xB9;
remote_mac[3] = 0x24;
remote_mac[4] = 0x14;
remote_mac[5] = 0x1E;
local_mac[0] = 0x00;
local_mac[1] = 0x1E;
local_mac[2] = 0xE3;
local_mac[3] = 0xED;
local_mac[4] = 0xD4;
local_mac[5] = 0xA9;
memcpy(eth->h_source, remote_mac, ETH_ALEN);
memcpy(eth->h_dest, remote_mac, ETH_ALEN);
Set device and protocol:
skb->protocol = htons(ETH_P_IP);
skb->dev = pfr->ring_netdev->dev;
skb->priority = sock->sk->sk_priority;
if(!err)
goto out_free;
Now send it
if (dev_queue_xmit(skb) != NETDEV_TX_OK) {
err = -ENETDOWN; /* Probably we need a better error here */
goto out;
}

Related

Could I Test CAN Tranceiver with External Loopback Mode?

Hello I am using STM32H753 over a custom PCB.
I have no any CAN Analyzer except oscilloscope, multimeter and logic analyzer.
We have a problem with CAN BUS communication.
I am suspecting of CAN Tranceiver but we couldn't find the root cause yet.
There are external and internal loopback modes in STM32H7 to test CAN, However these modes also allow us to see the messages what we sent on CAN TX.
I have two different product which has different STM32H753 variant. One is working and the other one is not. Their tranceivers are different but almost same pinout and behavior.
My assumption was if I see my messages on CAN TX then I have to see them CAN H and CAN L.
I wrote test code.
I tried both test code in both device.
On working one, I saw messages on CAN Tx and also see messages with in a suppress way which I thought because of no termination resistor at the end.
On the not-working one, I also saw messages at CAN TX and there is no any move at CAN H or CAN L.
My question is my test was is true or still I could miss something or this test does not imply anyhting ?
HAL_Delay(100);
if(HAL_FDCAN_AddMessageToTxBuffer(&hfdcan1, &TxHeader, TxData_Node1_To_Node2, FDCAN_TX_BUFFER0 ) != HAL_OK)
{
Error_Handler();
}
/* Send Tx buffer message */
if(HAL_FDCAN_EnableTxBufferRequest(&hfdcan1, FDCAN_TX_BUFFER0) != HAL_OK)
{
Error_Handler();
}
while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) == 1);
/* Polling for reception complete on buffer index 0 */
while(HAL_FDCAN_IsRxBufferMessageAvailable(&hfdcan1, FDCAN_RX_BUFFER0) == 0);
/* Retrieve message from Rx buffer 0. Rec msg from Node 2 */
if(HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_BUFFER0, &RxHeader, RxData_From_Node2) != HAL_OK)
{
Error_Handler();
}
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 1;
hfdcan1.Init.NominalSyncJumpWidth = 13;
hfdcan1.Init.NominalTimeSeg1 = 86;
hfdcan1.Init.NominalTimeSeg2 = 13;
hfdcan1.Init.DataPrescaler = 2;
hfdcan1.Init.DataSyncJumpWidth = 12;
hfdcan1.Init.DataTimeSeg1 = 12;
hfdcan1.Init.DataTimeSeg2 = 12;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0 ;
hfdcan1.Init.RxFifo0ElmtsNbr = 0;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 1;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 1;
hfdcan1.Init.TxFifoQueueElmtsNbr = 32;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}

to send the CAN frames after recieving ACK in CAPL (using delay/timer in CAPL)

I wrote a CAPl code, where it has to send the CAN frames to control the stepper motor step. stepper motor used is TMCM-1311 module.
variables{
message step myMsg1;
message llmmodule myMsg2;
message llmmodule myMg3;
}
on start{
int i=0;
for (i=0:;i<=5000:i++)
{
myMsg1.DLC = 8;
myMsg1.byte(0) = 0x04;
myMsg1.byte(1) = 0x01;
myMsg1.byte(2) = 0x00;
myMsg1.byte(3) = 0x00;
myMsg1.byte(4) = 0x00;
myMsg1.byte(5) = 0x00;
myMsg1.byte(6) = 0x0A;
myMsg1.byte(7) = 0x00;
output(mymsg1);
myMsg2.DLC = 8;
myMsg2.byte(0) = 0x07;
myMsg2.byte(1) = 0x01;
myMsg2.byte(2) = 0x03;
myMsg2.byte(3) = 0x11;
output(mymsg2);
myMsg3.DLC = 8;
myMsg3.byte(0) = 0x07;
myMsg3.byte(1) = 0x03;
myMsg3.byte(2) = 0x01;
myMsg3.byte(3) = 0x00;
output(mymsg3);
}
}
In the for loop of the above code, the CAN frame is continuously sent without waiting for the ACK, the 1st data frame i.e., myMsg1 is sent for rotating the stepper motor to certain step size, so once that frame is sent it takes some time for the stpper motor to rotate to that position, once it is at that position then the other 2 CAN frames i.e., myMsg2 and myMsg3 should be sent. After the ACK recieved for all the 3 data frames sent then i in the for loop should increment and the next iteration should take place. But in the above code the for loop is executing without waiting for the ACK from the CAN frame, so i think timer should be used there to give a delay and to execute the next iterations after the ACK is received. I tried using timers but i could not find a solution as required, so it would be great help if anyone can let me know how it should be executed.
You have to use the on message event for this use case.
variables
{
message step myMsg1;
message llmmodule myMsg2;
message llmmodule myMg3;
}
on start
{
myMsg1.DLC = 8;
myMsg1.byte(0) = 0x04;
myMsg1.byte(1) = 0x01;
myMsg1.byte(2) = 0x00;
myMsg1.byte(3) = 0x00;
myMsg1.byte(4) = 0x00;
myMsg1.byte(5) = 0x00;
myMsg1.byte(6) = 0x0A;
myMsg1.byte(7) = 0x00;
myMsg2.DLC = 8;
myMsg2.byte(0) = 0x07;
myMsg2.byte(1) = 0x01;
myMsg2.byte(2) = 0x03;
myMsg2.byte(3) = 0x11;
myMsg3.DLC = 8;
myMsg3.byte(0) = 0x07;
myMsg3.byte(1) = 0x03;
myMsg3.byte(2) = 0x01;
myMsg3.byte(3) = 0x00;
output(mymsg1);
}
on message ACK_Msg1
{
output(mymsg2);
}
on message ACK_Msg2
{
output(mymsg3);
}
on message ACK_Msg3
{
output(mymsg1);
}
This code will go on until the ack messages stop. So, if you want to do this for a definite amount of times, you might have to use some kind of flags in every event.

ParamValidationExt error with WelsInitEncoderExt failed while setting up OpenH264 encoder

Scenario:
I am using OpenH264 with my App to encode into a video_file.mp4.
Environment:
Platform : MacOs Sierra
Compiler : Clang++
The code:
Following is the crux of the code I have:
void EncodeVideoFile() {
ISVCEncoder * encoder_;
std:string video_file_name = "/Path/to/some/folder/video_file.mp4";
EncodeFileParam * pEncFileParam;
SEncParamExt * pEnxParamExt;
float frameRate = 1000;
EUsageType usageType = EUsageType::CAMERA_VIDEO_REAL_TIME;
bool denoise = false;
bool lossless = true;
bool enable_ltr = false;
int layers = 1;
bool cabac = false;
int sliceMode = 1;
pEncFileParam = new EncodeFileParam;
pEncFileParam->eUsageType = EUsageType::CAMERA_VIDEO_REAL_TIME;
pEncFileParam->pkcFileName = video_file_name.c_str();
pEncFileParam->iWidth = frame_width;
pEncFileParam->iHeight = frame_height;
pEncFileParam->fFrameRate = frameRate;
pEncFileParam->iLayerNum = layers;
pEncFileParam->bDenoise = denoise;
pEncFileParam->bLossless = lossless;
pEncFileParam->bEnableLtr = enable_ltr;
pEncFileParam->bCabac = cabac;
int rv = WelsCreateSVCEncoder (&encoder_);
pEnxParamExt = new SEncParamExt;
pEnxParamExt->iUsageType = pEncFileParam->eUsageType;
pEnxParamExt->iPicWidth = pEncFileParam->iWidth;
pEnxParamExt->iPicHeight = pEncFileParam->iHeight;
pEnxParamExt->fMaxFrameRate = pEncFileParam->fFrameRate;
pEnxParamExt->iSpatialLayerNum = pEncFileParam->iLayerNum;
pEnxParamExt->bEnableDenoise = pEncFileParam->bDenoise;
pEnxParamExt->bIsLosslessLink = pEncFileParam->bLossless;
pEnxParamExt->bEnableLongTermReference = pEncFileParam->bEnableLtr;
pEnxParamExt->iEntropyCodingModeFlag = pEncFileParam->bCabac ? 1 : 0;
for (int i = 0; i < pEnxParamExt->iSpatialLayerNum; i++) {
pEnxParamExt->sSpatialLayers[i].sSliceArgument.uiSliceMode = pEncFileParam->eSliceMode;
}
encoder_->InitializeExt(pEnxParamExt);
int videoFormat = videoFormatI420;
encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
int frameSize = frame_width * frame_height * 3 / 2;
int total_num = 500;
BufferedData buf;
buf.SetLength (frameSize);
// check the buffer before proceeding
if (buf.Length() != (size_t)frameSize) {
CloseEncoder();
return;
}
SFrameBSInfo info;
memset (&info, 0, sizeof (SFrameBSInfo));
SSourcePicture pic;
memset (&pic, 0, sizeof (SSourcePicture));
pic.iPicWidth = frame_width;
pic.iPicHeight = frame_height;
pic.iColorFormat = videoFormatI420;
pic.iStride[0] = pic.iPicWidth;
pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
pic.pData[0] = buf.data();
pic.pData[1] = pic.pData[0] + frame_width * frame_height;
pic.pData[2] = pic.pData[1] + (frame_width * frame_height >> 2);
for(int num = 0; num < total_num; num++) {
// try to encode the frame
rv = encoder_->EncodeFrame (&pic, &info);
}
if (encoder_) {
encoder_->Uninitialize();
WelsDestroySVCEncoder (encoder_);
}
}
Above code is something I pulled up from official usage examples of OpenH264 where BufferedData.h is a class I reused from OpenH264 utils
Issue:
But, I am getting the following error:
[OpenH264] this = 0x0x1038bc8c0, Error:ParamValidationExt(), width > 0, height > 0, width * height <= 9437184, invalid 0 x 0 in dependency layer settings!
[OpenH264] this = 0x0x1038bc8c0, Error:WelsInitEncoderExt(), ParamValidationExt failed return 2.
[OpenH264] this = 0x0x1038bc8c0, Error:CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.
Above does not crash the application but it goes through a blank run without creating the video_file.mp4 with the dummy data that I am trying to write into it.
Question:
There seems to be something wrong with the set up config I applying to pEnxParamExtwhich goes into encoder_->InitializeExt.
What am I doing wrong with the set up of the encoder?
Note:
I am not trying to hook up to any camera device. I am just trying to create a .mp4 video out of some dummy image data.
If you want to get complete and working OpenH264 Encoder Initialization procedure you can click... here.
According to your problem scenario, you are trying to create a video file(.mp4/.avi) from some dummy images. This task can be accomplished using two different libraries: i) Library for Codec, ii) Library for Container.
i) Library for Codec: It's so much easy to use a OpenH264 to compress data. One thing I must mention is that, OpenH264 always works with raw frames e.g. yuv420 data. So, if you want to compress your image data, you have to convert these image data into yuv420 color format. To get OpenH264 click... here
ii) Library for Container: After getting the encoded data you have to use another library to create the container with extension .mp4, .avi, .flv etc. There exists a lot of libraries in github to do that staff like FFmpeg, OpenCV, Bento4, MP4Maker, mp4parser etc. Before using these libraries please check in detail about the license issues. If you use FFmpeg, you will not need to use OpenH264 becuse FFmpeg itself works along with several codecs. You will also find lot more working examples as so many developers are working with video data out there.
Hope it helps. :)

Netmask returned in rt_msghdr2 in invalid format

I want to parse the routes returned by the kernel when invoking the sysctl function with the arguments: { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP2, 0 }.
After doing that I get several routing messages, in all of them I have found the issue: the struct sockaddr* at index RTAX_NETMASK doesn't contain a valid struct sockaddr.
The code to extract the addresses from the struct rt_msghdr2 returned by sysctl is the following:
// ROUNDUP Taken from route.c
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
struct rt_msghdr2* routeMsg = (struct rt_msgdr2*)buffer;
struct sockaddr* sockAddrArray[RTAX_MAX];
memset(sockAddrArray, 0, sizeof(sockAddrArray));
struct sockaddr* currentSockAddr;
currentSockAddr = (struct sockaddr*)(routeMsg + 1);
for (int i = 0; i < RTAX_MAX; i++) {
if (routeMsg->rtm_addrs & (1 << i)) {
sockAddrArray[i] = currentSockAddr;
currentSockAddr = (struct sockaddr *)(ROUNDUP(currentSockAddr->sa_len) + (char *)currentSockAddr);
}
else {
sockAddrArray[i] = NULL;
}
}
Even though the routeMsg states that it has a netmask, when I check the contents I find that it has something like this:
sockAddrArray[RTAX_NETMASK]->sa_len = 0
sockAddrArray[RTAX_NETMASK]->sa_type = \xff
sockAddrArray[RTAX_NETMASK]->sa_data = { \xff, \xff, \0, ...}
The weird thing is that the matching route on the host (based on the network and gateway addresses) has the netmask 255.255.255.0 which matches too well to the direct content of the of the netmask sockaddr.
Of course, I cannot trust anything else that comes after the RTAX_NETMASK in the array as it will be incorrectly parsed.
Does someone know why this happens?

LibSvm add features using the JAVA api

I have a text and I want to train by adding feature using the java API. Looking at the examples the main class to build the training set is the svm_problem. It appear like the svm_node represents a feature (the index is the feature and the value is the weight of the feature).
What I have done is to have a map (just to simplify the problem) that keeps an association between the feature and an index. For each of my weight> example I do create a new node :
svm_node currentNode = new svm_node();
int index = feature.getIndexInMap();
double value = feature.getWeight();
currentNode.index = index;
currentNode.value = value;
Is my intuition correct? What does the svm_problem.y refers to? Does it refer to the index of the label? Is the svm_problem.l just the length of the two vectors?
Your intuition is very close, but svm_node is a pattern not a feature. The variable svm_problem.y is an array that contains the labels of each pattern and svm_problem.l is the size of the training set.
Also, beware that svm_parameter.nr_weight is the weight of each label (useful if you have an unbalanced training set) but if you are not going to use it you must set that value to zero.
Let me show you a simple example in C++:
#include "svm.h"
#include <iostream>
using namespace std;
int main()
{
svm_parameter params;
params.svm_type = C_SVC;
params.kernel_type = RBF;
params.C = 1;
params.gamma = 1;
params.nr_weight = 0;
params.p= 0.0001;
svm_problem problem;
problem.l = 4;
problem.y = new double[4]{1,-1,-1,1};
problem.x = new svm_node*[4];
{
problem.x[0] = new svm_node[3];
problem.x[0][0].index = 1;
problem.x[0][0].value = 0;
problem.x[0][1].index = 2;
problem.x[0][1].value = 0;
problem.x[0][2].index = -1;
}
{
problem.x[1] = new svm_node[3];
problem.x[1][0].index = 1;
problem.x[1][0].value = 1;
problem.x[1][1].index = 2;
problem.x[1][1].value = 0;
problem.x[1][2].index = -1;
}
{
problem.x[2] = new svm_node[3];
problem.x[2][0].index = 1;
problem.x[2][0].value = 0;
problem.x[2][1].index = 2;
problem.x[2][1].value = 1;
problem.x[2][2].index = -1;
}
{
problem.x[3] = new svm_node[3];
problem.x[3][0].index = 1;
problem.x[3][0].value = 1;
problem.x[3][1].index = 2;
problem.x[3][1].value = 1;
problem.x[3][2].index = -1;
}
for(int i=0; i<4; i++)
{
cout << problem.y[i] << endl;
}
svm_model * model = svm_train(&problem, &params);
svm_save_model("mymodel.svm", model);
for(int i=0; i<4; i++)
{
double d = svm_predict(model, problem.x[i]);
cout << "Prediction " << d << endl;
}
/* We should free the memory at this point.
But this example is large enough already */
}

Resources