I have PC A connected to PC B via an ethernet cable.
One NIC from PC A is bound to DPDK.
EAL: Detected 4 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Probing VFIO support...
EAL: PCI device 0000:00:1f.6 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 8086:15d8 net_e1000_em
and is waiting/polling in rte_eth_rx_burst
I want to send something (just a ping) from PC B.
I've setup an IP to PC B and tried to ping another IP from that interface subnet.
Also, I've tried to configure PC B interface also as a DPDK and used a basic send app, but again nothing:
if (port_init(mbuf_pool) != 0) {
rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", 0);
}
struct Message {
char data[10];
};
struct ether_hdr *eth_hdr;
struct Message obj = {{'H','e','l','l','o','2','0','1','8'}};
struct Message *msg;
struct ether_addr s_addr = {{0x94,0xC6,0x91,0x14,0xAB,0xDD}};
struct ether_addr d_addr = {{0x94,0xC6,0x91,0x14,0xAB,0xDD}};
uint16_t ether_type = 0x0a00;
struct rte_mbuf * pkt[BURST_SIZE];
int i;
for(i=0;i<BURST_SIZE;i++) {
pkt[i] = rte_pktmbuf_alloc(mbuf_pool);
eth_hdr = rte_pktmbuf_mtod(pkt[i],struct ether_hdr*);
eth_hdr->d_addr = d_addr;
eth_hdr->s_addr = s_addr;
eth_hdr->ether_type = ether_type;
msg = (struct Message*) (rte_pktmbuf_mtod(pkt[i],char*) +
sizeof(struct ether_hdr));
*msg = obj;
int pkt_size = sizeof(struct Message) + sizeof(struct
ether_hdr);
pkt[i]->data_len = pkt_size;
pkt[i]->pkt_len = pkt_size;
}
uint16_t nb_tx = rte_eth_tx_burst(0,0,pkt,BURST_SIZE);
No bytes are received on my DPDK NIC.
Regarding the pings form B to A. Most probably the DPDK application does not answer ARP requests.
To fix: make sure you have added a correct static ARP entry on host B with arp -s.
Regarding the basic DPDK send. It has the same source and destination MACs, which is obviously wrong.
To fix: put the correct s_addr and d_addr of hosts B and A.
Related
I have a Raspberry Pi 4 running a C++ program where it receives and sends data via UDP. The RPi is setup as a UDP server.
The code for UDP.hpp is:
#pragma once
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>
using namespace std;
/////GLOBAL CONSTANTS/////
const int c_PORT = 8080;
class UDP
{
private:
int fdSocketUDP_; //File descriptor for UDP socket
int ClientAddressLength_; //Length of client address
struct sockaddr_in ServerAddress_; //Struct handling internet address for server
struct sockaddr_in ClientAddress_; //Struct handling internet address for client
public:
UDP(); //Initialize and bind socket
~UDP(); //Close socket
string readUDP(const int readSize); //Read via UDP protocol
void writeUDP(string message); //Write via UDP protocol
};
The code for UDP.cpp is:
#include "udp.hpp"
UDP::UDP()
{
if ((fdSocketUDP_ = socket(AF_INET, SOCK_DGRAM, 0)) < 0) //Create UDP socket
{
perror("Error - socket creation - udp.cpp");
exit(EXIT_FAILURE);
}
memset(&ServerAddress_, 0, sizeof(ServerAddress_)); //Sets ServerAddress_ to 0
memset(&ClientAddress_, 0, sizeof(ClientAddress_)); //Sets ClientAddress_ to 0
ServerAddress_.sin_family = AF_INET; //Address family, must be AF_INET = IPv4
ServerAddress_.sin_port = htons(c_PORT); //PORT number, convert PORT number to network byte order using htons()
ServerAddress_.sin_addr.s_addr = INADDR_ANY; //IP-Address of host (server IP), INADDR_ANY gets this IP Address
if (bind(fdSocketUDP_, (const struct sockaddr *)&ServerAddress_, sizeof(ServerAddress_)) < 0) //Bind the socket to ServerAddress_
{
perror("Error - socket bind - udp.cpp");
exit(EXIT_FAILURE);
}
}
UDP::~UDP()
{
close(fdSocketUDP_); //Close socket
}
string UDP::readUDP(const int readSize)
{
char readMsg[readSize] = {0}; //Read buffer
ClientAddressLength_ = sizeof(ClientAddress_);
if ((recvfrom(fdSocketUDP_, readMsg, readSize, 0, (struct sockaddr *)&ClientAddress_, (socklen_t *)&ClientAddressLength_)) < 0) //Receive data via UDP protocol
{
perror("Error - recvfrom - udp.cpp");
exit(EXIT_FAILURE);
}
string str(readMsg); //Convert char array to string
str = str.substr(0, readSize); //Make sure the string is the length of readsize
return str;
}
void UDP::writeUDP(string message)
{
//Make char array
int writeSize = message.size();
char writeMsg[writeSize + 1] = {'\0'};
//Convert string message to char array
for (int i = 0; i < writeSize; i++)
{
writeMsg[i] = message[i];
}
if ((sendto(fdSocketUDP_, writeMsg, writeSize, 0, (const struct sockaddr *)&ClientAddress_, (socklen_t)ClientAddressLength_)) < 0) //Send data via UDP protocol
{
perror("Error - sendto - udp.cpp");
exit(EXIT_FAILURE);
}
}
I then have a windows 10 laptop, running a Labview program that also receives and sends data via UDP. The laptop is setup as a UDP client. Below are som examples of the UDP setup in Labview.
Image 1 (Open UDP connection):
Image 2 (Close UDP connection):
Image 3 (Write and read UDP in Labview):
Above, the Labview program on the laptop sends 3 ("103") + 37 (not shown) bytes of data to the RPi, and then receives 16 bytes of data from the RPi.
The laptop and RPi are connected via a LAN-cable on a local network. The RPi uses IP-address 10.10.10.10 and port 8080, and the laptop uses IP-address 10.10.10.1 and port 1000.
Below are a Wireshark measurement, that measures the time between the different send and receive commands between the RPi and laptop.
Image 4 (wireshark measurement):
The "Len=3" is used by the RPi to determine what function to run in the C++ code. The "Len=52" and "Len=37" is data sent from the laptop (Labview) to the RPi (C++ code). The "Len=16" is data sent from the RPi to the laptop.
The laptop first sends 3+52 bytes of data to the RPi (client sends data to server). The laptop then sends 3+37 bytes of data to the RPi (client sends data to server). The RPi then sends 16 bytes of data back to the laptop (server sends data to client)... and so on.
One command (3+52 bytes or 3+37+16 bytes) takes about ~8ms to finish, with ~2ms latency (on average) between each command. As you can see, the data sizes between the RPi and laptop are "relatively" small (3/37/52 bytes).
Now my problem: Sometimes there is a delay of ~20ms between the commands (10 times longer than the average of ~2ms), and I don't know why... (this is shown with the red dots on image 4). This delay often comes after the RPi (UDP server) sends data to the laptop (UDP client - the 16 bytes of data), but it can happen at different places, as shown on image 4 (after the laptop sends 52 bytes to the RPi). I think it has something to do with the UDP, maybe the setup, maybe it has something to do with ARP, but I don't know. I have tried overclocking the RPi, tweaking the priority of the C++ program on the RPi, tweaking the C++ code, but that doesn't seem to be the bottleneck.
It's like the UDP connection between the laptop and RPi is "lost" or "paused" sometimes and it then takes some time for the connection to come back on track.
I found a solution to my problem. To solve the long delay, i had to lower the UDP read buffer, since i'm only sending small packages via UDP.
To do this, i formatted the sysctl.conf file on the RPi, located in the /etc folder.
I added the lines:
net.core.rmem_default = 4096
net.core.rmem_max = 4096
I'm currently working on a project need to broadcast the data packet to a common port D88 for every second, but the client can not receive the data packet. I'm not sure I'm using the right way to send the packet.
int sockfdBroad;
struct sockaddr_in addrBroad;
swStat.packetBroadSent=0;
sockfdBroad=socket(AF_INET,SOCK_DGRAM,0);
bzero(&addrBroad,sizeof(addrBroad));
addrBroad.sin_family = AF_INET;
addrBroad.sin_addr.s_addr=inet_addr("192.168.1.255");
addrBroad.sin_port=htons(3464);
if ((cycles%1000)==0)
{
currenttime = getMicrosTimeStamp();
createTimePacket(bufferTime,currenttime,Odroid_Trigger);
sendto(sockfdBroad,bufferTime,PACKET_LENGTH_TIME,0,(struct sockaddr *)&addrBroad,sizeof(addrBroad));
swStat.packetBroadSent++;
}
Assuming that the netmask for 192.168.1.255 is 255.255.255.0, 192.168.1.255 is a broadcast address. From man ip(7):
Datagrams to broadcast addresses can be only sent or received when the SO_BROADCAST socket flag is set.
In other words, both the sender and the receiver must do:
int value = 1;
if(-1 == setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &value, sizeof value))
// Handle error.
If you check the return value of sendto it must be -1 and errno == EACCESS. Always check the return values.
Running a Linux system on a PowerPC Architecture which is connected via Ethernet to another Device obtaining a UDP connection (Package Based),
I try to setup a socket and bind it to my Port 8813. But whenever I enter a Port different from 0, Binding fails.
Here is the code:
int connector::initUDPSocket(){
struct hostent *server;
//Construct Socket
struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}
;
sockaddr_in socketaddress;
socklen_t addrlen = sizeof(struct sockaddr_in); /* length of addresses */
udpsocket=socket(AF_INET,SOCK_DGRAM ,0);
if(udpsocket<=0)
{
printf("No Socket opened!");
return 1;
}
else
{
printf("ONE Socket opened!");
memset((char *) &socketaddress,0, sizeof(socketaddress));
socketaddress.sin_family = AF_INET;
socketaddress.sin_addr.s_addr=htonl(inet_addr("192.168.0.10"));//<=That's the external devices address;// htonl(inet_addr("192.168.0.1"));//<=That's my devices address;//htonl(INADDR_ANY);//INADDR_ANY;//
socketaddress.sin_port = htons(8813);//8813;//htonl(8813);//htons(0); //<=Only the last one works
int bind_result=bind(udpsocket,(struct sockaddr *)&socketaddress,sizeof(socketaddress));
if( bind_result == SOCKET_ERROR)
{
printf(LFL_CRI,"BIND failed! Error: %s",strerror(errno)); //Returns "BIND failed! Error: Address family not supported by protocol"
}
else
{
printf(LFL_CRI,"BIND worked!");
//Nun den Listener für den DatenStream aufsetzen.
char SockAddrBuffer[sizeof(struct sockaddr_storage)];
socklen_t SockAddrBufferSize = sizeof(SockAddrBuffer);
int numofbytes=recvfrom(udpsocket, udp_buffer, UDP_BUFFERSIZE, 0, (struct sockaddr *)SockAddrBuffer, &SockAddrBufferSize);
if (numofbytes >0)
{
printf("%i bytes received",numofbytes);
}
}
}
return 0;
}
}
What I found out so far:
Ping 192.168.0.10 is possible
Data seem not to be blocked by the firewall; iptables -nvL mentioned no dropped packages. I added a new rule for that, before this rule was applied, the number or dropped packages increased when the external device was connected.
Using a test tool on my Windows PC (simply debugging, if there's incoming traffic on a port; connecting the external device to it), I receive data; so, the external device definitely sends data
Binding to Port 0 works; the netstat -au mentions a tool listening on port 2, while the program is running
Error Message: BIND failed! Error: Address family not supported by protocol
So, 2 questions are open here:
What am I doing wrong?
What am I understanding wrong about "bind". What sense does it make to listen to "some random port assigned to my program by the system"? I mean, if I setup an http-Server, I want to listen to Port 80 and not to port "RANDOM". What is this good for?
You've redefined struct sockaddr_in in your code. If is in any way different from how the system defines it, any code that attempts to use this struct will not work properly.
You need to #include <netinet/in.h> to get the proper definition of this struct.
I am trying to get NFS disk quotas via rpc protocol. By using OpenMP, i am creating parallel udp connections. The program runs without any error with 1 and 2 core. When i increase core number to 4, after a while program gives "RPC: Port mapper failure - RPC: Unable to send" error on "clntudp_create()" function, which is creating udp connection . I am using following code for this job.
/*
* 0 -> True
* 1 -> Couldn't resolve hostname
* 2 -> Udp connection couldn't initiate
* 3 -> Query couldn't run
* 4 -> Unknown error
*/
long long int diskOfUser::getNfsQuota(string blockDevice, int uid)
{
//some address resolving operations
int whereToSplit = blockDevice.find(':');
if(whereToSplit == std::string::npos)
return 5;
std::string host = blockDevice.substr(0, whereToSplit);
std::string path = blockDevice.substr(whereToSplit+1, blockDevice.size() - whereToSplit);
char *pathToGo = new char[path.size()+1];
strcpy(pathToGo,path.c_str());
char *hostToGo = new char[host.size()+1];
strcpy(hostToGo,host.c_str());
//variable definitions
struct getquota_args *gqArgs;
gqArgs = new struct getquota_args;
struct getquota_rslt *gqRslt; //quota result object
gqRslt = new struct getquota_rslt;
struct sockaddr_in server_addr; //udp connection address
struct hostent *hp;
struct timeval timeout, totTimeOut; //timeout values
CLIENT *client = NULL; //udp client
int socket = RPC_ANYSOCK;
timeout.tv_usec = 0;
timeout.tv_sec = 6;
totTimeOut.tv_sec = 25;
totTimeOut.tv_usec = 0;
//try to resolve host
if ((hp = gethostbyname(hostToGo)) == NULL)
{
delete pathToGo;
delete hostToGo;
return 1; //hostname couldn't resolve
}
/* Try to start UDP connection (Problematic part)*/
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(875);
memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
server_addr.sin_port = 0;
if ((client = clntudp_create(&server_addr, (u_long)100011, (u_long)1, timeout, &socket)) == NULL)
{
delete pathToGo;
delete hostToGo;
clnt_pcreateerror("error"); // gives the following error "RPC: Port mapper failure - RPC: Unable to send"
return 2; //udp connection could not start
}
/* UDP connection created */
//quota asking operations ...
}
Is there any way to make this job thread safe?
EDIT: "RPC: Unable to send; errno = Bad file descriptor" clnt_sperror() function is giving this error. I am starting four process with one core separately, program is running with no error. But 1 process with 4 core is always blowing up.
ANSWER:
/* UDP connection oluşturuluyor */
if ((client = clnt_create(hostToGo, (u_long)100011, (u_long)1, "UDP")) == NULL)
{
delete pathToGo;
delete hostToGo;
return 2; //rquotad ile udp connection oluşturma işlemi başarısız oldu
}
/* UDP connection oluşturuldu */
client->cl_auth = authunix_create_default(); //rpc authentication handle
gqArgs->gqa_uid = uid; //argumanlar set ediliyor
gqArgs->gqa_pathp = pathToGo;
I reached my goal with clnt_create() function. It is thread safe alternative of clntudp_create(). But, on the server side rquota.d seralizing all the request and answering one by one. Because of this it is not fully optimize.
I am working on a cross-platform game using C/C++ and socket. I am using UDP broadcast (e.g. send to xx.xx.xx.255 if on a C-type LAN address) for discovering of nearby players in LAN game playing.
The issue is the Mac/iOS version can not receive broadcast UDP packet that sent by others (neither from Mac/iOS , nor from windows), while windows version is able the receive broadcast packet from Mac/iOS. Thus Mac/iOS can not discover any nearby players while windows can discover all nearby players. On the same socket handle, sending/receiving normal UDP packet works on all platforms (sent to a specific address instead of the broadcast address).
Every testing device has only one NIC, which is connected to a single WIFI router. Addresses are dynamically allocated by DHCP on the WIFI router. The socket is bind to exact local address instead of 0.0.0.0, and I am using port 19190. [ Thanks for reading my question :) ]
Following is the code for initializing the socket on all platforms. I do set the SO_BROADCAST flag on Mac/iOS otherwise UDP broadcast packet won't be sent successfully.
BOOL Socket::__Create(const struct sockaddr &BindTo, int addr_len, int nSocketType, BOOL reuse_addr, int AF)
{
ASSERT(m_hSocket == INVALID_SOCKET);
m_hSocket = socket(AF, nSocketType, 0);
if(INVALID_SOCKET != m_hSocket)
{
int on = 1;
if(SOCK_STREAM == nSocketType)
{ linger l = {1,0};
VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_LINGER,(char*)&l,sizeof(linger)));
#if defined(PLATFORM_MAC) || defined(PLATFORM_IOS)
VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_NOSIGPIPE,(void *)&on, sizeof(on)));
#endif
}
#if defined(PLATFORM_MAC) || defined(PLATFORM_IOS)
else if(SOCK_DGRAM == nSocketType)
{
VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_BROADCAST,(void *)&on, sizeof(on)));
}
#endif
if(reuse_addr)
{ VERIFY(0==setsockopt(m_hSocket,SOL_SOCKET,SO_REUSEADDR,(char*)&on,sizeof(on)));
}
if(0==bind(m_hSocket,&BindTo,addr_len))
{
return TRUE;
}
}
_LOG_WARNING("Socket Error = "<<GetLastError());
Close();
return FALSE;
}
Here is the receiving code:
BOOL Socket::__RecvFrom(LPVOID pData, UINT len, UINT& len_out, struct sockaddr &target, int addr_len, BOOL Peek)
{
SOCKET_SIZE_T la = addr_len;
int l = (int)recvfrom(m_hSocket,(char*)pData,len,Peek?MSG_PEEK:0,&target,&la);
if(l==SOCKET_ERROR)return FALSE;
len_out = l;
return la == addr_len;
}
Did you try to bind the socket to the broadcast address (the one you are sending to) ? – ElderBug
Also, it's not working when you bind to 0.0.0.0 ? – ElderBug