My node-red flow includes an udp-out node with my computer's ip address. But this changes from time to time, so then I manually need to change it. The tooltip for the UDP-out node says to leave the address blank if you want to use msg.ip to set.
How do I use msg.ip? I haven't find a solution to this. It keeps reporting udp address not set.
You leave it blank in the config dialog for the node, then on EVERY message you want to send out via the node you need to set msg.ip to the ip address you want to send the message to.
The following flow demonstrates:
[{"id":"238e2695.98a252","type":"udp out","z":"59370ac1.51144c","name":"","addr":"","iface":"","port":"","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":547.5,"y":181,"wires":[]},{"id":"2a002216.f8cb3e","type":"inject","z":"59370ac1.51144c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":141.5,"y":180,"wires":[["6d51ce96.66603"]]},{"id":"6d51ce96.66603","type":"change","z":"59370ac1.51144c","name":"","rules":[{"t":"set","p":"ip","pt":"msg","to":"ip","tot":"flow"},{"t":"set","p":"port","pt":"msg","to":"port","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":353.5,"y":180,"wires":[["238e2695.98a252"]]}]
It assumes you set the flow.ip and flow.port from some other source in the flow.
Related
We're using DPDK (version 20.08 on ubuntu 20.04, c++ application) to receive UDP packets with a high throughput (>2 Mpps). We use a Mellanox ConnectX-5 NIC (and a Mellanox ConnectX-3 in an older system, would be great if the solution worked there aswell).
Contrary, since we only need to send a few configuration messages, we send messages through the default network stack. This way, we can use lots of readily available tools to send configuration messages; however, since all the received data is consumed by DPDK, these tools do not get back any messages.
The most prominent issue arises with ARP negotiation: the host tries to resolve addresses, the clients also do respond properly, however, these responses are all consumed by DPDK such that the host cannot resolve the addresses and refuses to send the actual UDP packets.
Our idea would be to filter out the high throughput packets on our application and somehow "forward" everything else (e.g. ARP responses) to the default network stack. Does DPDK have a built-in solution for that? I unfortunatelly coulnd't find anything in the examples.
I've recently heard about the packet function which allows to inject packets into SOCK_DGRAM sockets which may be a possible solution. I also couldn't find a sample implementation for our use-case, though. Any help is greatly appreciated.
Theoretically, if the NIC in question supports the embedded switch feature, it should be possible to intercept the packets of interest in the hardware and redirect them to a virtual function (VF) associated with the physical function (PF), with the PF itself receiving everything else.
The user configures SR-IOV feature on the NIC / host as well as virtualisation support;
For a given NIC PF, the user adds a VF and binds it to the corresponding Linux driver;
The DPDK application is run with the PF ethdev and a representor ethdev for the VF;
To handle the packets in question, the application adds the corresponding flow rules.
The PF (ethdev 0) and the VF representor (ethdev 1) have to be explicitly specified by the corresponding EAL argument in the application: -a [pci:dbdf],representor=vf0.
As for the flow rules, there should be a pair of such.
The first rule's components are as follows:
Attribute transfer (demands that matching packets be handled in the embedded switch);
Pattern item REPRESENTED_PORT with port_id = 0 (instructs the NIC to intercept packets coming to the embedded switch from the network port represented by the PF ethdev);
Pattern items matching on network headers (these provide narrower match criteria);
Action REPRESENTED_PORT with port_id = 1 (redirects packets to the VF).
In the second rule, item REPRESENTED_PORT has port_id = 1, and action REPRESENTED_PORT has port_id = 0 (that is, this rule is inverse). Everything else should remain the same.
It is important to note that some drivers do not support item REPRESENTED_PORT at the moment. Instead, they expect that the rules be added via the corresponding ethdevs. This way, for the provided example: the first rule goes to ethdev 0, the second one goes to ethdev 1.
As per the OP update, the adapter in question might indeed support the embedded switch feature. However, as noted above, item REPRESENTED_PORT might not be supported. The rules should be inserted via specific ethdevs. Also, one more attribute, ingress, might need to be specified.
In order to check whether this scheme works, one should be able to deploy a VF (as described above) and run testpmd with the aforementioned EAL argument. In the command line of the application, the two flow rules can be tested as follows:
flow create 0 ingress transfer pattern eth type is 0x0806 / end actions represented_port ethdev_port_id 1 / end
flow create 1 ingress transfer pattern eth type is 0x0806 / end actions represented_port ethdev_port_id 0 / end
Once done, that should pass ARP packets to the VF (thus, to the network interface) in question. The rest of packets should be seen by testpmd in active forwarding mode (start command).
NOTE: it is recommended to switch to the most recent DPDK release.
For the current use case, the best option is to make use of DPDK TAP PMD (which is part of LINUX DPDK). You can use Software or Hardware to filter the specific packets then sent it desired TAP interface.
A simple example to demonstrate the same would be making use DPDK skeleton example.
build the DPDK example via cd [root folder]/example/skeleton; make static
pass the desired Physical DPDK PMD NIC using DPDK eal options ./build/basicfwd -l 1 -w [pcie id of DPDK NIC] --vdev=net_tap0;iface=dpdkTap
In second terminal execute ifconfig dpdkTap 0.0.0.0 promisc up
Use tpcudmp to capture Ingress and Egress packets using tcpdump -eni dpdkTap -Q in and tcpdump -enu dpdkTap -Q out respectively.
Note: you can configure ip address, setup TC on dpdkTap. Also you can run your custom socket programs too. You do not need to invest time on TLDP, ANS, VPP as per your requirement you just need an mechanism to inject and receive packet from Kernel network stack.
In all Diameter implementations I saw, the messages originating from the server is always sent towards the DNS resolved IP address of whats in the Destination-Host AVP. But, in commercial servers, we see an option to configure a DRA or a DEA which takes in all the messages and routes them.
Thus, when it comes to the mobicents diameter stack, this approach is sometimes hard to do. I can anyway re-configure the hosts file so that the message ends up in a DRA/DEA, yet, its a pain. I see no option to send these messages to a central diameter agent which will take care of all the dirty work for me.
The next issue is, if I plan to create such a DRA/DEA, the stack does not accept messages to a different host. Where, the message's Destination-Host parameter might contain a different hostname than ours. (which would be the ultimate destination it needs to go)
Is there a hack to achieve this without meddling with the internals of the jdiameter code and RA code?
If you change jdiameter's config to something like this:
<Network>
<Peers>
<Peer name="aaa://127.0.0.1:21812" attempt_connect="false" rating="1" />
<Peer name="aaa://CUSTOM_HOST:4545" attempt_connect="false" rating="1" />
</Peers>
<Realms>
<Realm name="custom.realm" peers="CUSTOM_HOST" local_action="LOCAL" dynamic="false" exp_time="1">
<ApplicationID>
...
</ApplicationID>
</Realm>
</Realms>
</Network>
In your sbb, then you'll need to create a client session providing your custom realm using this method:
DiameterCCAResourceAdaptor.CreditControlProviderImpl.createClientSession(DiameterIdentity destinationHost, DiameterIdentity destinationRealm)
Example:
ccaRaSbb.createClientSession(null, "custom.realm")
where ccaRaSbb is a CreditControlProvider instance (resource adaptor interface)
finally, when creating your CCR, the method CreditControlClientSession.createCreditControlRequest() will use the session' realm to find an available peer previously configured.
Let me know if this makes sense to you
Posting the method I used to solve this problem.
As it turns out its not possible out of the box to send a diameter message towards a peer which is not configured in the stack's jdiameter-config.xml file.
For me, the option to alter the stack in this case was also not feasible. So I devised a workaround for the problem by co-operating with the DRA we have. (most DRA's should be able to handle this method)
I added two custom AVPs to the outgoing request, namely Ultimate-Destination-Host and Ultimate-Destination-Realm.
In the DRA, I asked the admin to delete my Destination-Host and Destination-Realm AVPs and replace them with the ones created in step 1.
Now, whenever I send a packet destined to other diameter peers outside the configured peer, I target them towards the DRA and set these 'Ultimate' destination AVPs.
Ours is an Oracle DSR which is capable of doing this AVP manipulation. Most commercial ones should be able to handle it. Hope someone who wanted an answer for this question found this useful.
If I open up a port on our server to listen out for incoming messages (ie - strings of text), how can i send those messages? are their any example codes out there that are useful?
I have downloaded a few sample projects but none seem to do i want.
what code is used to specify the ip address and port number?
Here you wil find exactly what you need.
It is a wrapper class called AsyncSocket; to connect you just send it the string with the ip and an int with the port.
It will do all the work on ints own.
To send info you just turn your string into NSData if I remember correctly.
It has a very easy to follow sample so you should be up and running in about 20 min.
Look up any tutorial text on networking.
For instance, there are a bunch of echo server implmentations at rosettacode.
I'm writing a SIP stack, and I need to insert an ip address in the message. This address needs to be the one used for sending the message. I know the destination IP and need to determine the NIC (its address) that will be used to send the message....
To expand a bit on Remy Lebeau's comment, GetBestInterfaceEx() is your best bet, if you're on Windows XP or newer. That will work for both IPv4 and IPv6 addresses.
GetBestInterface/GetBestInterfaceEx return the index (call it IDX) of the most appropriate interface to use to contact some address.
Then you can map that index into a local IP address by getting your interface<->IP address mapping using GetIpAddrTable or GetAdaptersAddresses if you're dual-stacking (supporting both IPv6 and IPv4).
Iterate over that table and find the interface with the dwIndex (or IfIndex, in the case of GetAdaptersAddresses) matching IDX.
It's usually best to allow the IP address your SIP stack will operate on to be set as an adjustable configuration option. It means the user will need to set a configuration option but at least your stack will know the IP address it's operating on.
If that's not feasible then an approach you could use is to send out the SIP request on all IP addresses using a dummy value in the Via header such as 0.0.0.0 and set the interface you get a response back on as the default one. This approach alos as the advantage that the SIP response will tell you the public IP address the request was received from which can be useful if your SIP stack is behind a NAT.
Over TCP, I think you can get the address of the local side of the socket after connect(). I don't know if the same is true for UDP (I suspect not), but it might be worth a try.
The socket will allow you to Bind to a local endpoint before calling connect (both UDP and TCP).
That is all ok if you know the port. However, if you want the port to be ephemeral (e.g. some random port number) then you must come up with your own algorithm to do so and robust code to handle the cases where the port is exclusivly taken by another application.
I am writing a UDP test client/server and i want to get it through firewall. Supposedly all i need to do is have both sides send to the correct IP and server. Getting an IP is not a problem but how do i have the client pick a random free port and report it to the user? I eventually would want it to connect to a matchmaker server but right now i need a simple working prototype and i would like to cout the port number so my friend/tester can send me the # via IM so we can test.
How do i get the port number?
sorry for the long desc. I notice people tell me not to do what i am asking when i dont give a desc :(
To use the highly technical term, this is actually a pretty icky problem or even a pair of icky problems. Depending on the configuration of the firewall, it will usually allow responses from another endpoint on the IP endpoint as the request came from. So... if you friend receives the UDP datagram using something like the recvfrom() system call, the address parameter will receive the IP endpoint information to respond to. So the other end should be able to respond with a sendto() using the same addressing information. Something like:
/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));
/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);
The peeraddr on the other side will be your external address or, more correctly, the IP address of your firewall and the port number that it chose to use. The port number that you specify in your code may be completely different than the port that your friend would have to send data to. Ultimately, it might not matter what port you choose to use since the firewall might be sending and receiving on an entirely different port - this is what Network Address Translation is all about. I would recommend reading RFC3235 for some tips on how to overcome that hurdle.
The best approach IMHO is to:
Let the OS choose a port by either calling bind() with a zero port number or skipping the bind altogether
Having the client receive the address information from the socket layer (e.g., the fifth and sixth arguments to recvfrom())
The client sends response to the endpoint retrieved in the previous step
Tweak the firewall configurations until the previous steps work
Of course, all of the magic is in the last step. If you can disable NAT or ensure that the firewall is never going to switch ports, then nailing down a port number and bind-ing to it will work as well. You might want to take a look at %WINDIR%\system32\drivers\etc\services (or /etc/services depending on your OS inclination) to get an idea of what port numbers are reserved or generally in use.
bind() the socket before you send your data. Specify port 0 to bind(), and the OS will pick an unused port for you. You can then use getsockname() to find out what port wsa chosen.
Generally speaking - you - as the developer - choose the port. You can set your application to read the port from a config file or user input - but no magic firewall is going to tell you what port to use...
If I'm understanding your question correctly, I'm not sure there's a way to do what you want programatically (and even if there is, I don't think it's the right approach). I think you need to find a port that isn't in use on the server machine (and perhaps a different or the same port on the client machine, if communication is bi-directional) AND that port must be able to pass through your firewall. I assume since you say "getting an IP is not a problem", you've already configured your firewall to forward some or all ports to a specific computer inside the firewall? If so, the port you seek is one of the ones you forwarded. You can just pick an arbitrary one, as long as no other service is running on that port. Ports below 1024 are reserved, so you probably want to pick a higher number than that. You can use a simple portscanning tool such as nmap to see which services are running on your computer on which ports and pick a different one. Note that nmap can be fooled by firewalls and various bind rules when sockets are created.
I think you're better off picking a fixed port rather than relying on the random port number chosen by the O/S.
If you use a random port you'd have to change your firewall settings each and every time you run the program.
If you're using WINSOCK check this link:
http://msdn.microsoft.com/en-us/library/aa280717(VS.60).aspx
Basically you have 2 choices set the port to 0 and let the system assign you one or chose a random one try to open the socket if it doesn't work try another (be sure to steer clear of reserved ports)